树和二叉树

未完结 

1.结点的定义

1 typedef struct Node
2 {
3     struct Node *lchild;
4     struct Node *rchild;
5     int data;
6 }BiTreeNode,*BiTree; 
7 //*BiTree的意思是给struct Node*起了个别名叫BiTree,所以BiTree为指向结点的指针。
二叉树的结点定义

 

2.二叉树的建立

 1 void Creat_BiTree(BiTree &T)
 2 {
 3     int n;
 4     scanf("%d",&n);
 5     if(n==-1)
 6     {
 7         T = NULL;
 8     }
 9     else
10     {
11         T = (BiTree) malloc(sizeof(struct Node));
12         T->data = n;
13         Creat_BiTree(T->lchild);
14         Creat_BiTree(T->rchild);
15     }
16 }
利用递归前序建立二叉树

 

 1 void level_creat(BiTree &T,int *level,int n)
 2 {
 3     int i=0;
 4     T = (BiTree) malloc(sizeof(struct Node));
 5     T->data = *level;
 6     BiTree queue[n];
 7     int l=0,r=0;
 8     queue[r++]=T;
 9     while(i<n)
10     {
11         BiTree S = queue[l++];
12         if(2*i+1 < n && 2*i+2<n)  //有两个孩子
13         {
14             S->lchild = (BiTree) malloc(sizeof(struct Node));
15             S->lchild->data = *(level+(2*i+1));
16             S->rchild = (BiTree) malloc(sizeof(struct Node));
17             S->rchild->data = *(level+(2*i+2));
18             queue[r++]=S->lchild;
19             queue[r++]=S->rchild;
20         }
21         else if(2*i+1<n &&2*i+2>=n) //有左孩子
22         {
23             S->lchild = (BiTree) malloc(sizeof(struct Node));
24             S->lchild->data = *(level+(2*i+1));
25             S->rchild = NULL;
26             queue[r++]=S->lchild;
27         }
28         else if(2*i+1>=n) //有左孩子
29         {
30             S->lchild = NULL;
31             S->rchild = NULL;
32         }
33         i++;
34     }
35 }
根据层次顺序建立二叉树

 

 1 void pre_in_creat(BiTree &T,int *pre,int *in,int n)
 2 {
 3     if(n<1)
 4     {
 5         T=NULL;
 6         return ;
 7     }
 8     T = (BiTree) malloc(sizeof(struct Node));
 9     T ->data = *pre;
10     int *in_root = in;
11     int i=0;
12     while(*(in_root+i) != *pre) i++;
13 
14     pre_in_creat(T->lchild,pre+1,in,i);
15     pre_in_creat(T->rchild,pre+i+1,in+i+1,n-i-1);
16 }
给定前序和中序数组建立二叉树

 

 1 void post_in_creat(BiTree &T,int *post,int *in,int n)
 2 {
 3     if(n<1)
 4     {
 5         T=NULL;
 6         return;
 7     }
 8     T = (BiTree) malloc(sizeof(struct Node));
 9 
10     int x = *(post+n-1);
11     T->data = x;
12     int *in_root = in;
13     int i=0;
14     while(*(in_root+i)!=x) i++;
15 
16     post_in_creat(T->lchild,post,in,i);
17     post_in_creat(T->rchild,post+i,in+i+1,n-i-1);
18 
19 }
给定后序和中序数组建立二叉树

 

3.二叉树的遍历

1 void preorder(BiTree &T)
2 {
3     if(T!=NULL)
4     {
5         printf("%d ",T->data);
6         preorder(T->lchild);
7         preorder(T->rchild);
8     }
9 }
递归前序遍历输出结点的值

 

1 void inorder(BiTree &T)
2 {
3     if(T!=NULL)
4     {
5         inorder(T->lchild);
6         printf("%d ",T->data);
7         inorder(T->rchild);
8     }
9 }
递归中序遍历输出结点的值

 

1 void postorder(BiTree &T)
2 {
3     if(T!=NULL)
4     {
5         postorder(T->lchild);
6         postorder(T->rchild);
7         printf("%d ",T->data);
8     }
9 }
递归后序遍历输出结点的值

 

 1 void N_preorder(BiTree T)
 2 {
 3     BiTree Stack[100];
 4     BiTree S = T;
 5     if(T!=NULL)
 6     {
 7         int top = -1;
 8         Stack[++top] = S;   //根节点入栈
 9         while(top>-1)        //当栈不为空时循环
10         {
11             S = Stack[top--];            // 根节点出栈
12             printf("%d ",S->data);       // 先往栈里放右子树再放左子树 这样出栈时才会先左后右
13             if(S->rchild)
14             {
15                 Stack[++top] = S->rchild;
16             }
17             if(S->lchild)
18             {
19                 Stack[++top]=S->lchild;
20             }
21         }
22     }
23 }
非递归前序

 

 1 void N_inorder(BiTree T)
 2 {
 3     BiTree Stack[100];
 4     BiTree S = T;
 5     if(T!=NULL)
 6     {
 7         int top = -1;
 8         while(top > -1 || S)
 9         {
10             while(S)
11             {
12                 Stack[++top]=S;        //将结点左路下的所有结点入栈
13                 S = S->lchild;    
14             }
15             if(top>-1)
16             {
17                 S = Stack[top--]; 
18                 printf("%d ",S->data);   
19                 S = S->rchild;         //转向右子树
20             }
21         }
22 
23     }
24 }
非递归中序

 

 1 void N_postorder(BiTree T)
 2 {
 3     BiTree Stack[100];
 4     int top = -1;
 5     //前驱结点
 6     BiTree pre = NULL;
 7     //当前结点
 8     BiTree cur = NULL;
 9     if(T!=NULL)
10     {
11         Stack[++top] = T;
12         while(top>-1)
13         {
14             cur = Stack[top];
15             /*
16             如果P不存在左孩子和右孩子,则可以直接访问它;或者P存在左孩子
17             或者右孩子,但是其左孩子和右孩子都已被访问过了,则同样可以直接访问该结点。
18             */
19             if( (cur->lchild==NULL && cur->rchild==NULL) || (pre!=NULL && (cur->lchild==pre || cur->rchild==pre)))
20             {
21                 printf("%d ",cur->data);
22                 top--;
23                 pre = cur;
24             }
25             /*
26             若非上述两种情况,则将P的右孩子和左孩子依次入栈,这样就保证了每次取栈
27             顶元素的时候,左孩子在右孩子前面被访问,左孩子和右孩子都在根结点前面被访问。
28             */
29             else
30             {
31                 if(cur->rchild)
32                 {
33                     Stack[++top] = cur->rchild;
34                 }
35                 if(cur->lchild)
36                 {
37                     Stack[++top] = cur->lchild;
38                 }
39             }
40         }
41     }
42 
43 }
非递归后序

 

 1 void levelorder(BiTree &T)
 2 {
 3     BiTree queue[20];
 4     int l=0,r=0;
 5     if(T!=NULL)
 6     {
 7         queue[r++] = T;
 8         while(l!=r)
 9         {
10             T = queue[l];
11             printf("%d ",T->data);
12             if(T->lchild!=NULL)
13             {
14                 queue[r++]= T->lchild;
15             }
16             if(T->rchild!=NULL)
17             {
18                 queue[r++]= T->rchild;
19             }
20             l++;
21         }
22     }
23 }
利用队列思想层次遍历

 

 4.二叉树的基本算法

 1 int getHeigh(BiTree T)
 2 {
 3     if(T==NULL) return 0;
 4     if(T)
 5     {
 6         int left = getHeigh(T->lchild);
 7         int right = getHeigh(T->rchild);
 8         if(left > right) return left+1;
 9         else return right+1;
10     }
11 }
求二叉树的高度

 

1 递归左树节点数加上右树节点数加1
2 int getNum(BiTree T)
3 {
4     if(T == NULL) return 0;
5 
6     int left = getNum(T->lchild);
7     int right = getNum(T->rchild);
8     return left+right+1;
9 }
求二叉树的结点总数

 

1 int getLeafNum(BiTree T)
2 {
3     if(T==NULL) return 0;
4     if(T->lchild==NULL && T->rchild == NULL) return 1;
5     return getLeafNum(T->lchild)+getLeafNum(T->rchild);
6 
7 }
求二叉树叶子结点的总数

 

1 int getNumOfK(BiTree T,int k)
2 {
3     if(T==NULL) return 0;
4     if(k==1) return 1;
5     return getNumOfK(T->lchild,k-1) +getNumOfK(T->rchild,k-1);
6 }
求二叉树第K层的结点个数

 

1 BiTree Find(BiTree T,int x)
2 {
3     if(T == NULL) return NULL;
4     if(T->data == x) return T;
5     return Find(T->lchild,x);
6     return Find(T->rchild,x);
7 }
按值查找二叉树上的结点

 

 1 bool IsSame(BiTree A,BiTree B)
 2 {
 3 
 4     if(A==NULL && B==NULL) return true;
 5     if(A==NULL || B==NULL) return false;
 6     if(A->data!=B->data) return false;
 7 
 8     return IsSame(A->lchild,B->lchild)&&IsSame(A->rchild,B->rchild);
 9 
10 }
判断两个树是否为同一棵树

 

 5.二叉树的应用

 

1 根据后序和中序遍历输出先序遍历 

本题要求根据给定的一棵二叉树的后序遍历和中序遍历结果,输出该树的先序遍历结果。

输入格式:

第一行给出正整数N(30),是树中结点的个数。随后两行,每行给出N个整数,分别对应后序遍历和中序遍历结果,数字间以空格分隔。题目保证输入正确对应一棵二叉树。

输出格式:

在一行中输出Preorder:以及该树的先序遍历结果。数字间有1个空格,行末不得有多余空格。

输入样例:

7
2 3 1 5 7 6 4
1 2 3 4 5 6 7

输出样例:

Preorder: 4 1 3 2 6 5 7
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <malloc.h>
 4 using namespace std;
 5 typedef struct Node
 6 {
 7     struct Node *lchild;
 8     struct Node *rchild;
 9     int data;
10 }BiTreeNode,*BiTree;
11 void post_in_creat(BiTree &T,int *post,int *in,int n)
12 {
13     if(n<1) {T=NULL;return ;}
14     int *in_root = in;
15     int x = *(post+n-1);
16     int i=0;
17     while(*(in_root+i)!=x) i++;
18     T = (BiTree)malloc(sizeof(struct Node));
19     T->data = x;
20     post_in_creat(T->lchild,post,in,i);
21     post_in_creat(T->rchild,post+i,in+i+1,n-i-1);
22 }
23 void preorder(BiTree T)
24 {
25     if(T!=NULL)
26     {
27         printf(" %d",T->data);
28         preorder(T->lchild);
29         preorder(T->rchild);
30     }
31 }
32 int main()
33 {
34     int n;
35     scanf("%d",&n);
36     int in[n];
37     int post[n];
38     for(int i=0;i<n;i++)
39     {
40         scanf("%d",&post[i]);
41     }
42     for(int i=0;i<n;i++)
43     {
44         scanf("%d",&in[i]);
45     }
46     BiTree T;
47     post_in_creat(T,post,in,n);
48     printf("Preorder:");
49     preorder(T);
50 }
根据后序和中序遍历输出先序遍历

 

 

2 树的同构 

给定两棵树T1和T2。如果T1可以通过若干次左右孩子互换就变成T2,则我们称两棵树是“同构”的。例如图1给出的两棵树就是同构的,因为我们把其中一棵树的结点A、B、G的左右孩子互换后,就得到另外一棵树。而图2就不是同构的。

 


 

图1

图2

现给定两棵树,请你判断它们是否是同构的。

 

输入格式:

输入给出2棵二叉树树的信息。对于每棵树,首先在一行中给出一个非负整数N (10),即该树的结点数(此时假设结点从0到N1编号);随后N行,第i行对应编号第i个结点,给出该结点中存储的1个英文大写字母、其左孩子结点的编号、右孩子结点的编号。如果孩子结点为空,则在相应位置上给出“-”。给出的数据间用一个空格分隔。注意:题目保证每个结点中存储的字母是不同的。

输出格式:

如果两棵树是同构的,输出“Yes”,否则输出“No”。

输入样例1(对应图1):

8
A 1 2
B 3 4
C 5 -
D - -
E 6 -
G 7 -
F - -
H - -
8
G - 4
B 7 6
F - -
A 5 1
H - -
C 0 -
D - -
E 2 -

输出样例1:

Yes

输入样例2(对应图2):

8
B 5 7
F - -
A 0 3
C 6 -
H - -
D - -
G 4 -
E 1 -
8
D 6 -
B 5 -
E - -
H - -
C 0 2
G - 3
F - -
A 1 4

输出样例2:

No
 1 #include <iostream>
 2 #include <cstdio>
 3 using namespace std;
 4 typedef struct
 5 {
 6     char data;
 7     int lchild;
 8     int rchild;
 9 }Tree;
10 bool Isomprphic(Tree T1[],Tree T2[],int root1,int root2)
11 {
12     if(root1 == -1 && root2 == -1) return true;
13     if((root1 == -1 && root2 != -1) || (root1 != -1&& root2==-1) ) return false;
14     if(T1[root1].data!=T2[root2].data) return false;
15     if(T1[root1].lchild==-1 && T2[root2].lchild == -1)
16         return Isomprphic(T1,T2,T1[root1].rchild,T2[root2].rchild);
17     if(T1[T1[root1].lchild].data == T2[T2[root2].lchild].data )
18         return Isomprphic(T1,T2,T1[root1].rchild,T2[root2].rchild);
19     else
20         return Isomprphic(T1,T2,T1[root1].rchild,T2[root2].lchild) && Isomprphic(T1,T2,T1[root1].lchild,T2[root2].rchild);
21 }
22 int getRoot(Tree T[])
23 {
24     int n;
25     scanf("%d",&n);
26     getchar();
27     int check[n]={0};
28     int root = -1;
29     char c,ch1,ch2;
30     for(int i=0;i<n;i++)
31     {
32         scanf("%c %c %c",&c,&ch1,&ch2);
33         getchar();
34         T[i].data = c;
35         if(ch1 == '-') T[i].lchild = -1;
36         else
37         {
38             T[i].lchild=ch1-'0';
39             check[ch1-'0'] = 1;
40         }
41         if(ch2 == '-') T[i].rchild=-1;
42         else
43         {
44             T[i].rchild=ch2-'0';
45             check[ch2-'0'] = 1;
46         }
47     }
48     for(int i=0;i<n;i++)
49     {
50         if(!check[i])
51         {
52             root = i;
53             return root;
54         }
55     }
56     return root;
57 }
58 
59 
60 int main()
61 {
62     Tree T1[100],T2[100];
63     int root1 = getRoot(T1);
64     int root2 = getRoot(T2);
65     if(Isomprphic(T1,T2,root1,root2))
66         printf("Yes");
67     else printf("No");
68 }
树的同构

 

3.是否同一棵二叉搜索树 (25 分)

给定一个插入序列就可以唯一确定一棵二叉搜索树。然而,一棵给定的二叉搜索树却可以由多种不同的插入序列得到。例如分别按照序列{2, 1, 3}和{2, 3, 1}插入初始为空的二叉搜索树,都得到一样的结果。于是对于输入的各种插入序列,你需要判断它们是否能生成一样的二叉搜索树。

输入格式:

输入包含若干组测试数据。每组数据的第1行给出两个正整数N (10)和L,分别是每个序列插入元素的个数和需要检查的序列个数。第2行给出N个以空格分隔的正整数,作为初始插入序列。最后L行,每行给出N个插入的元素,属于L个需要检查的序列。

简单起见,我们保证每个插入序列都是1到N的一个排列。当读到N为0时,标志输入结束,这组数据不要处理。

输出格式:

对每一组需要检查的序列,如果其生成的二叉搜索树跟对应的初始序列生成的一样,输出“Yes”,否则输出“No”。

输入样例:

4 2
3 1 4 2
3 4 1 2
3 2 4 1
2 1
2 1
1 2
0

输出样例:

Yes
No
No

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <malloc.h>
 4 using namespace std;
 5 typedef struct Node
 6 {
 7     struct Node *lchild;
 8     struct Node *rchild;
 9     int data;
10 }*BiTree;
11 void creat(BiTree &T,int x)
12 {
13     if(T==NULL)
14     {
15         T = (BiTree)malloc(sizeof(struct Node));
16         T->data = x;
17         T->lchild = T->rchild = NULL;
18     }
19     else
20     {
21         if(x>T->data)
22         {
23             creat(T->rchild,x);
24         }
25         else if(x<T->data)
26         {
27             creat(T->lchild,x);
28         }
29     }
30 }
31 bool IsSame(BiTree A,BiTree B)
32 {
33     if(A==NULL && B==NULL) return true;
34     if(A==NULL||B==NULL) return false;
35     if(A->data!=B->data) return false;
36     return IsSame(A->lchild,B->lchild) &&IsSame(A->rchild,B->rchild);
37 }
38 int main()
39 {
40     int n,m;
41 
42     while(scanf("%d",&n))
43     {
44         if(n==0) break;
45         scanf("%d",&m);
46         int x;
47         BiTree A=NULL;
48         for(int i=0;i<n;i++)
49         {
50             scanf("%d",&x);
51             creat(A,x);
52         }
53         while(m--)
54         {
55             BiTree B=NULL;
56             for(int i=0;i<n;i++)
57             {
58                 scanf("%d",&x);
59                 creat(B,x);
60             }
61             if(IsSame(A,B))printf("Yes\n");
62             else printf("No\n");
63         }
64     }
65 }
是否为同一棵二叉树
是否完全二叉搜索树 (30 分)

将一系列给定数字顺序插入一个初始为空的二叉搜索树(定义为左子树键值大,右子树键值小),你需要判断最后的树是否一棵完全二叉树,并且给出其层序遍历的结果。

输入格式:

输入第一行给出一个不超过20的正整数N;第二行给出N个互不相同的正整数,其间以空格分隔。

输出格式:

将输入的N个正整数顺序插入一个初始为空的二叉搜索树。在第一行中输出结果树的层序遍历结果,数字间以1个空格分隔,行的首尾不得有多余空格。第二行输出YES,如果该树是完全二叉树;否则输出NO

输入样例1:

9
38 45 42 24 58 30 67 12 51

输出样例1:

38 45 24 58 42 30 12 67 51
YES

输入样例2:

8
38 24 12 45 58 67 42 51

输出样例2:

38 45 24 58 42 12 67 51
NO


  1 #include <iostream>
  2 #include <cstdio>
  3 #include <malloc.h>
  4 using namespace std;
  5 typedef struct Node
  6 {
  7     struct Node *lchild;
  8     struct Node *rchild;
  9     int data;
 10 }*BiTree;
 11 int n;
 12 void creat(BiTree &T,int x)
 13 {
 14     if(T==NULL)
 15     {
 16         T = (BiTree)malloc(sizeof(struct Node));
 17         T->data = x;
 18         T->lchild = T->rchild = NULL;
 19     }
 20     else
 21     {
 22         if(x<T->data)
 23         {
 24             creat(T->rchild,x);
 25         }
 26         else if(x>T->data)
 27         {
 28             creat(T->lchild,x);
 29         }
 30     }
 31 }
 32 void preorder(BiTree T)
 33 {
 34     if(T)
 35     {
 36         printf(" %d",T->data);
 37         preorder(T->lchild);
 38         preorder(T->rchild);
 39     }
 40 }
 41 void levelorder(BiTree T)
 42 {
 43     BiTree q[n];
 44     int l=0,r=0;
 45     int w=0;
 46     q[r++]=T;
 47     while(l<r)
 48     {
 49         T = q[l++];
 50         w++;
 51         if(w==n) printf("%d\n",T->data);
 52         else printf("%d ",T->data);
 53         if(T->lchild)
 54         {
 55             q[r++] = T->lchild;
 56         }
 57         if(T->rchild)
 58         {
 59             q[r++] = T->rchild;
 60         }
 61 
 62     }
 63 }
 64 bool IsComplete(BiTree T)
 65 {
 66     if(T==NULL) return true;
 67     BiTree q[n];
 68     int l=0,r=0;
 69     q[r++]=T;
 70     int shouldleaf = 0;
 71     while(l<r)
 72     {
 73         T = q[l++];
 74         if(T->lchild)
 75         {
 76             q[r++] = T->lchild;
 77         }
 78         if(T->rchild)
 79         {
 80             q[r++] = T->rchild;
 81         }
 82         if(T->rchild&&!T->lchild) return false;
 83         if(shouldleaf == 1 && (T->lchild||T->rchild)) return false;
 84         if( (T->lchild&&!T->rchild) || (!T->lchild&&!T->rchild) ) shouldleaf = 1;
 85 
 86     }
 87     return true;
 88 }
 89 int main()
 90 {
 91     int x;
 92     scanf("%d",&n);
 93     BiTree T=NULL;
 94     for(int i=0;i<n;i++)
 95     {
 96         scanf("%d",&x);
 97         creat(T,x);
 98     }
 99     levelorder(T);
100     if(IsComplete(T))
101     {
102         printf("YES");
103     }
104     else
105 
106     {
107         printf("NO");
108     }
109 }
是否完全二叉搜索树

 

 
posted @ 2018-12-03 21:46  谋莽台  阅读(226)  评论(0编辑  收藏  举报