09:44:07 2019-08-28
学习
昨天做了 课程要求的 PTA的三道题
基本上涉及了 树的建立 以及树的遍历
今天把昨天 学到的树的遍历 的非递归 实现了一下
写的过程也不是特别顺利 看来 知道代码怎么一回事 和 把代码写出 还是有很大区别的
利用 前序中序后序遍历 以及 层序遍历 输出该树
1 #define _CRT_SECURE_NO_WARNINGS //vs中scanf为不安全的函数 要使用 得加上这句话 2 #include<stdio.h> 3 #define Size 10 4 struct TreeNode 5 { 6 char Data; 7 int LeftChild; 8 int RightChild; 9 int times; //为例后序遍历的非递归使用 10 }Tree[10]; 11 int Stack[10]; 12 int STop; //栈顶下标 13 void Push(int Num) 14 { 15 Stack[STop++] = Num; 16 } 17 int Pop() 18 { 19 return Stack[--STop]; 20 } 21 int IsEmpty() 22 { 23 return !STop; 24 } 25 26 int Queue[10]; 27 int Front = 1; 28 int Rear = 0; 29 int QSize; 30 int Succ(int num) //判断是否越界 31 { 32 if (num < Size) 33 return num; 34 else 35 return 0; 36 } 37 void EnQueue(int num) 38 { 39 Rear = Succ(Rear+1); 40 Queue[Rear] =num; 41 QSize++; 42 } 43 int DeQueue() 44 { 45 int num = Queue[Front]; 46 Front = Succ(Front+1); 47 QSize--; 48 return num; 49 } 50 51 //非递归实现遍历 52 //前序中序后序遍历 的非递归做法都是利用栈 因为 前序中序后序的访问顺序是一样的 53 void InOrderTraversal(int Bt); //中序遍历 54 void PreOrderTraversal(int Bt); //先序遍历 55 void PostOrderTraversal(int Bt); //后序遍历 56 57 //层序遍历的做法是利用 队列 58 void LevelOrderTraversal(int Bt); //层序遍历 59 60 void InOrderTraversal(int Bt) 61 { 62 while (Bt!=-1||!IsEmpty()) //空树不输出 如果栈内还有元素 得输出 63 { 64 while (Bt != -1) 65 { 66 Push(Bt); //第一次遇见 67 Bt = Tree[Bt].LeftChild; 68 } 69 if (!IsEmpty()) 70 { 71 int T = Pop(); //第二次遇见 输出 72 printf("%c ", Tree[T].Data); 73 Bt = Tree[T].RightChild; //转向右节点 74 } 75 } 76 } 77 void PreOrderTraversal(int Bt) 78 { 79 while (Bt != -1 || !IsEmpty()) //空树不输出 如果栈内还有元素 得输出 80 { 81 while (Bt != -1) 82 { 83 Push(Bt); //第一次遇见 输出 84 printf("%c ", Tree[Bt].Data); 85 Bt = Tree[Bt].LeftChild; 86 } 87 if (!IsEmpty()) 88 { 89 int T = Pop(); 90 Bt = Tree[T].RightChild; //转向右节点 91 } 92 } 93 } 94 void PostOrderTraversal(int Bt) 95 { 96 while (Bt != -1 || !IsEmpty()) //空树不输出 如果栈内还有元素 得输出 97 { 98 while (Bt != -1) 99 { 100 Push(Bt); //第一次遇见 101 Tree[Bt].times++; 102 Bt = Tree[Bt].LeftChild; 103 } 104 if (!IsEmpty()) 105 { 106 int T = Pop(); 107 if (Tree[T].times == 2) //判断是否第三次遇见 108 printf("%c ", Tree[T].Data); //第三次遇见 输出 109 else 110 { 111 Push(T); 112 Tree[T].times++; 113 Bt = Tree[T].RightChild; //第二次遇见 转向右孩子 114 } 115 } 116 } 117 } 118 119 void LevelOrderTraversal(int Bt) 120 { 121 if (Bt == -1) //空树 122 return; 123 EnQueue(Bt); //首先必须进队 根节点 124 while (QSize) //队列不为空 125 { 126 int T= DeQueue(); 127 printf("%c ", Tree[T].Data); 128 if (Tree[T].LeftChild != -1) EnQueue(Tree[T].LeftChild); 129 if (Tree[T].RightChild != -1)EnQueue(Tree[T].RightChild); 130 } 131 } 132 int Convert(char num) //将字符转换为数字 133 { 134 if (num == '-') 135 return -1; 136 else 137 return num - '0'; 138 } 139 int BuildTree() //利用 数组建树 140 { 141 int Root=-1; //记录根节点 142 int N=0; 143 int Check[10] = { 0 }; //用来判断根节点的位置 144 scanf("%d\n", &N); 145 for(int i=0;i<N;i++) 146 { 147 char Data, Num1, Num2; 148 scanf("%c %c %c\n", &Data, &Num1, &Num2); 149 Tree[i].Data = Data; 150 Tree[i].LeftChild = Convert(Num1); 151 Tree[i].RightChild = Convert(Num2); 152 if (Tree[i].LeftChild != -1)Check[Tree[i].LeftChild] = 1; 153 if (Tree[i].RightChild != -1)Check[Tree[i].RightChild] = 1; 154 } 155 for (int i = 0; i < N; i++) 156 { 157 if (!Check[i]) 158 Root = i; 159 } 160 return Root; 161 } 162 int main() 163 { 164 int Tree; 165 Tree = BuildTree(); 166 InOrderTraversal(Tree); printf("\n");//中序遍历 167 PreOrderTraversal(Tree); printf("\n"); //先序遍历 168 PostOrderTraversal(Tree); printf("\n"); //后序遍历 169 LevelOrderTraversal(Tree); //层次遍历 170 }