数据结构学习第十二天
09:43:33 2019-08-27
努力
对于非空二叉树 ${n_0}$是表示叶节点的个数
${n_0}+{n_1}+{n_2}-{1}=0*{n_0}+1*{n_1}+2*{n_2}$
即可得出
${n_0}={n_2}+{1}$
二叉树的遍历方法
PTA 第6题 判断2个树是否同构
1 #define _CRT_SECURE_NO_WARNINGS 2 #include<stdio.h> 3 #include<stdlib.h> 4 struct TreeNode 5 { 6 char Data; 7 int LChild; 8 int RChild; 9 }Tree1[10],Tree2[10]; 10 11 int Change(const char num) //将读入的字符修改后返回 12 { 13 if (num != '-') 14 return num - '0'; 15 else 16 return -1; 17 } 18 int Charge(int T1,int T2) //判别2个树是否重构 19 { 20 if (T1 == -1 && T2 == -1) //都为空树 为同构 21 return 1; 22 if ((T1 == -1 && T2 != -1) || (T1 != -1 && T2 == -1)) //一空 一不空 不同构 23 return 0; 24 if (Tree1[T1].Data != Tree2[T2].Data) //节点的值不一样 不同构 25 return 0; 26 if (Tree1[T1].LChild == -1 && Tree2[T2].LChild == -1) //无左子树 27 return Charge(Tree1[T1].RChild, Tree2[T2].RChild); 28 if ((Tree1[T1].LChild != -1 && Tree2[T2].LChild != -1) && Tree1[Tree1[T1].LChild].Data == Tree2[Tree2[T2].LChild].Data) 29 return (Charge(Tree1[T1].LChild, Tree2[T2].LChild) && Charge(Tree1[T1].RChild, Tree2[T2].RChild)); 30 else 31 return (Charge(Tree1[T1].LChild, Tree2[T2].RChild) && Charge(Tree1[T1].RChild, Tree2[T2].LChild)); 32 } 33 int BulidTree(struct TreeNode Tree[]) 34 { 35 int N; 36 int Root=0; 37 int Check[10] = { 0 }; //用数组来记录哪个值未出现 38 scanf("%d", &N); 39 if (!N) 40 { 41 Root = -1; 42 } 43 char c, num1, num2; 44 for (int i = 0; i < N; i++) 45 { 46 getchar(); 47 scanf("%c %c %c", &c, &num1, &num2); 48 Tree[i].Data = c; 49 Tree[i].LChild = Change(num1); //对字符进行改变 并返回整数 50 if (Tree[i].LChild != -1) Check[Tree[i].LChild] = 1; 51 Tree[i].RChild = Change(num2); 52 if (Tree[i].RChild != -1) Check[Tree[i].RChild] = 1; 53 } 54 for (int i = 0; i < N; i++) 55 if (!Check[i]) 56 { 57 Root = i; 58 break; 59 } 60 return Root; 61 } 62 int main() 63 { 64 int TreeA, TreeB; 65 TreeA = BulidTree(Tree1); 66 TreeB = BulidTree(Tree2); 67 if (Charge(TreeA,TreeB)) 68 printf("Yes"); 69 else 70 printf("No"); 71 }
PTA 第7题 找出所有树叶
1 #define _CRT_SECURE_NO_WARNINGS 2 #include<stdio.h> 3 #include<stdlib.h> 4 #define Size 10 5 int Queue[10]; 6 int Front=1; 7 int Rear=0; 8 int size = 0; 9 int Num[10] = { 0 };//用来收集数据 10 int j = -1; //用于访问数组 11 int Succ(int n) 12 { 13 if (n < Size) 14 return n; 15 else 16 return 0; 17 } 18 void EnQueue(int num) 19 { 20 Rear = Succ(Rear + 1); 21 Queue[Rear] = num; 22 size++; 23 } 24 int DeQueue() 25 { 26 size--; 27 int num = Queue[Front]; 28 Front = Succ(Front+1); 29 return num; 30 } 31 struct TreeNode 32 { 33 int LChild; 34 int RChild; 35 }Tree[10]; 36 int Change(char num) 37 { 38 if (num == '-') 39 return -1; 40 else 41 return num - '0'; 42 } 43 int BuildTree(struct TreeNode T[]) 44 { 45 int Root=-1; 46 int N=0; 47 int Check[10] = { 0 }; //记录哪个节点未出现 48 scanf("%d", &N); 49 for (int i = 0; i < N; i++) 50 { 51 getchar(); 52 char num1, num2; 53 scanf("%c %c", &num1, &num2); 54 T[i].LChild = Change(num1); 55 T[i].RChild = Change(num2); 56 if (T[i].LChild != -1) Check[T[i].LChild] = 1; 57 if (T[i].RChild != -1) Check[T[i].RChild] = 1; 58 } 59 for (int i = 0; i < N; i++) 60 if (!Check[i]) 61 { 62 Root = i; 63 break; 64 } 65 return Root; 66 } 67 void FindLeves(int T) //利用队列实现层序遍历 68 { 69 if (T == -1) 70 return; 71 //int i = 0; //用来计算 A2的个数 72 EnQueue(T); 73 while (size) 74 { 75 int t = DeQueue(); 76 if(Tree[t].LChild!=-1)EnQueue(Tree[t].LChild); 77 if(Tree[t].RChild!=-1)EnQueue(Tree[t].RChild); 78 if (Tree[t].RChild != -1 && Tree[t].RChild != -1); 79 if (Tree[t].LChild == -1 && Tree[t].RChild == -1) 80 Num[++j] = t; 81 /*if(i) 82 printf("%d ", t); 83 else 84 printf("%d", t);*/ 85 } 86 } 87 88 int main() 89 { 90 int T; 91 T = BuildTree(Tree); 92 FindLeves(T); 93 for (int i = 0; i <=j; i++) 94 { 95 if(i!=j) 96 printf("%d ", Num[i]); 97 else 98 printf("%d", Num[i]); 99 } 100 return 0; 101 }
写第题是格式出了问题 题上要求最后末位不能多个空格 我想在最后加上printf("\b") 但是不行
后面又想用 二叉树中后代为0与后代为2的关系 即$A_0=A_2+1$ 来做 也不行 上网也没搜到好方法(可能我没认真看) 最后老老实实拿数组做了
PTA 第8题 已知前序遍历和中序遍历 输出 后序遍历 (os:课程上说这道题不难 我做了好几个小时。。。我是憨憨)
1 #define _CRT_SECURE_NO_WARNINGS 2 #include<stdio.h> 3 #include<stdlib.h> 4 #include<string.h> 5 struct TreeNode 6 { 7 int LChild; 8 int RChild; 9 }Tree[50]; 10 int size; //记录大小 因为最后一个值后不加空格 11 int l; 12 int Stack[30]; 13 int i; //栈的标志 14 int Pre[30]; //记录前序遍历的结果 1,2,3,4,5,6 15 int j; 16 int Inorder[30]; //记录中序遍历的结果 3,2,4,1,6,5 17 int k; 18 void Scan() 19 { 20 int N = 0; 21 scanf("%d\n", &N); 22 N *= 2; 23 char Str[10] = { 0 }; 24 int num; 25 while (N--) 26 { 27 scanf("%s ", Str); 28 if (!strcmp(Str,"Push")) 29 { 30 scanf("%d\n", &Pre[j++]); 31 Stack[i++] = Pre[j - 1]; 32 } 33 else 34 { 35 Inorder[k++] = Stack[--i]; 36 } 37 } 38 size =k; 39 } 40 int BuildTree(int lo1,int hi1,int lo2,int hi2) 41 { 42 int root = Pre[lo1]; //递归中的第一个值都是 要求的节点 43 for (int m =lo2; m < hi2; m++) 44 { 45 if (root == Inorder[m]) 46 { 47 if (lo1 + 1 < lo1 + 1 + m-lo2)Tree[root].LChild = BuildTree(lo1 + 1, lo1 + 1 + m-lo2, lo2, m); //不断递归 缩减问题规模 48 else Tree[root].LChild=-1; //当大小缩小至1时 为树叶 49 if (lo1+1+m <lo1+hi2)Tree[root].RChild = BuildTree(lo1 + 1 + m - lo2, lo1+hi2, m + 1, hi2); 50 else Tree[root].RChild=-1; 51 } 52 } 53 return root; //返回 节点 54 } 55 void Print(int Root) 56 { 57 if(Root!=-1) 58 { 59 Print(Tree[Root].LChild); 60 Print(Tree[Root].RChild); 61 if (size-->1) 62 printf("%d ", Root); 63 else 64 printf("%d", Root); 65 } 66 } 67 int main() 68 { 69 Scan(); 70 int Root=BuildTree(0,j,0,k); 71 Print(Root); 72 return 0; 73 }
何佬在视频中讲过 已知 三种遍历方式中(前序中序后序)知道其中两个 可以确定二叉树的情况是 :必须存在中序遍历
利用递归 不断缩减问题规模 先用 前序遍历和中序遍历 确定好二叉树并 读入到 数组中(用动态也可以)
然后递归输出 后序遍历