未完结
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//有两个孩子 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 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 }
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 #include2 #include 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 ) 39 { 40 scanf("%d",&post[i]); 41 } 42 for(int i=0;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到N−1编号);随后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 #include2 #include 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 ) 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 ) 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 #include2 #include 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 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 ) 49 { 50 scanf("%d",&x); 51 creat(A,x); 52 } 53 while(m--) 54 { 55 BiTree B=NULL; 56 for(int i=0;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 #include2 #include 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 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 ) 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 }