5.3.2二叉树的遍历
(1)前序遍历二叉树的递归定义
若二叉树非空,则依次进行操作:1 访问根结点;2 前序遍历左子树;3 前序遍历右子树。
(2)中序遍历二叉树的递归定义
若二叉树非空,则依次进行操作:1 中序遍历左子树;2 访问根结点;3 中序遍历右子树。
(3)后序遍历二叉树的递归定义
若二叉树非空,则依次进行操作:1 后序遍历左子树;2 后序遍历右子树;3 访问根结点。
C实现
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 typedef char DataType; 5 6 struct node 7 { 8 DataType data; 9 struct node * lchild, *rchild; 10 }; 11 typedef struct node BinTNode; 12 13 BinTNode * CreateBinTree();//二叉树的生成 14 void Preorder(BinTNode * bt);//前序遍历二叉链表算法 15 void Inorder(BinTNode * bt);//中序遍历二叉链表算法 16 void Postorder(BinTNode * bt);//后序遍历二叉链表算法 17 18 void main() 19 { 20 BinTNode * bt = CreateBinTree();//二叉树的生成 21 22 Preorder(bt);//前序遍历二叉链表算法 23 printf(" "); 24 25 Inorder(bt);//中序遍历二叉链表算法 26 printf(" "); 27 28 Postorder(bt);//后序遍历二叉链表算法 29 printf(" "); 30 31 system("pause"); 32 } 33 34 BinTNode * CreateBinTree() 35 { 36 BinTNode * pa = (BinTNode *)malloc(sizeof(BinTNode)); 37 BinTNode * pb = (BinTNode *)malloc(sizeof(BinTNode)); 38 BinTNode * pc = (BinTNode *)malloc(sizeof(BinTNode)); 39 BinTNode * pd = (BinTNode *)malloc(sizeof(BinTNode)); 40 BinTNode * pe = (BinTNode *)malloc(sizeof(BinTNode)); 41 42 pa->data = 'A'; 43 pb->data = 'B'; 44 pc->data = 'C'; 45 pd->data = 'D'; 46 pe->data = 'E'; 47 48 pa->lchild = pb; 49 pa->rchild = pc; 50 pb->lchild = pb->rchild = NULL; 51 pc->lchild = pd; 52 pc->rchild = NULL; 53 pd->lchild = NULL; 54 pd->rchild = pe; 55 pe->lchild = pe->rchild = NULL; 56 57 return pa; 58 } 59 60 void Preorder(BinTNode * bt)//前序遍历二叉链表算法 61 { 62 if (bt != NULL) 63 { 64 printf("%c", bt->data);//访问根结点 65 Preorder(bt->lchild);//前序遍历左子树 66 Preorder(bt->rchild);//前序遍历右子树 67 } 68 } 69 70 void Inorder(BinTNode * bt)//中序遍历二叉链表算法 71 { 72 if (bt != NULL) 73 { 74 Inorder(bt->lchild);//中序遍历左子树 75 printf("%c", bt->data);//访问根结点 76 Inorder(bt->rchild);//中序遍历右子树 77 } 78 } 79 80 void Postorder(BinTNode * bt)//后序遍历二叉链表算法 81 { 82 if (bt != NULL) 83 { 84 Postorder(bt->lchild);//后序遍历左子树 85 Postorder(bt->rchild);//后序遍历右子树 86 printf("%c", bt->data);//访问根结点 87 } 88 }
输出结果
ABCDE
BADEC
BEDCA
请按任意键继续. . .
1递归遍历算法
2非递归遍历算法
C++实现
void Preorder(BinTNode *bt);//前序遍历二叉链表算法
void Inorder(BinTNode *bt);//中序遍历二叉链表算法
void Postorder(BinTNode *bt);//后序遍历二叉链表算法
void Inorder1(BinTNode *bt);//利用栈的非递归中序遍历算法
void Inorder2(BinTNode *bt);//用指针数组来实现二叉树非递归中序遍历算法
int getyenum(BinTNode *bt);//统计叶子结点数量
int BinTreeDepth(BinTNode *bt);//二叉树的深度
void TransLevel(BinTNode *bt);//非递归的按层遍历二叉链表树
int getfather(BinTNode *bt, int num);//查找二叉树的父结点
int getleft(BinTNode *bt, int num);//查找二叉树的某个结点的左兄弟
int findmax(BinTNode *bt);//查找二叉树的最大值
BinTNode *insertnode(BinTNode *bt, int num);//二叉树插入
1 #include <iostream> 2 #include <stack> 3 #include <queue> 4 5 typedef struct node 6 { 7 int data; 8 struct node *lchild = nullptr, *rchild = nullptr; 9 }BinTNode; 10 11 void Preorder(BinTNode *bt);//前序遍历二叉链表算法 12 void Inorder(BinTNode *bt);//中序遍历二叉链表算法 13 void Postorder(BinTNode *bt);//后序遍历二叉链表算法 14 void Inorder1(BinTNode *bt);//利用栈的非递归中序遍历算法 15 void Inorder2(BinTNode *bt);//用指针数组来实现二叉树非递归中序遍历算法 16 int getyenum(BinTNode *bt);//统计叶子结点数量 17 int BinTreeDepth(BinTNode *bt);//二叉树的深度 18 void TransLevel(BinTNode *bt);//非递归的按层遍历二叉链表树 19 int getfather(BinTNode *bt, int num);//查找二叉树的父结点 20 int getleft(BinTNode *bt, int num);//查找二叉树的某个结点的左兄弟 21 int findmax(BinTNode *bt);//查找二叉树的最大值 22 BinTNode *insertnode(BinTNode *bt, int num);//二叉树插入 23 24 void main() 25 { 26 BinTNode *root; 27 28 BinTNode s1; 29 BinTNode s2; 30 BinTNode s3; 31 BinTNode s4; 32 BinTNode s5; 33 BinTNode s6; 34 BinTNode s7; 35 36 root = &s1; 37 38 s1.data = 1; 39 s2.data = 2; 40 s3.data = 3; 41 s4.data = 4; 42 s5.data = 5; 43 s6.data = 6; 44 s7.data = 7; 45 46 s1.lchild = &s2; 47 s1.rchild = &s3; 48 s2.lchild = &s4; 49 s2.rchild = &s5; 50 s3.lchild = &s6; 51 s3.rchild = &s7; 52 53 Preorder(root);//前序遍历二叉链表算法 54 std::cout << " "; 55 Inorder(root);//中序遍历二叉链表算法 56 std::cout << " "; 57 Postorder(root);//后序遍历二叉链表算法 58 std::cout << " "; 59 60 Inorder1(root);//利用栈的非递归中序遍历算法 61 std::cout << " "; 62 63 Inorder2(root);//用指针数组来实现二叉树非递归中序遍历算法 64 std::cout << " "; 65 66 std::cout << getyenum(root) << std::endl;//统计叶子结点数量 67 68 std::cout << BinTreeDepth(root) << std::endl;//二叉树的深度 69 70 TransLevel(root);//非递归的按层遍历二叉链表树 71 std::cout << " "; 72 73 std::cout << getfather(root, 3) << std::endl;//查找二叉树的父结点 74 75 std::cout << getleft(root, 3) << std::endl;//查找二叉树的某个结点的左兄弟 76 77 std::cout << findmax(root) << std::endl;//查找二叉树的最大值 78 79 insertnode(root, 8);//二叉树插入 80 root = &s1; 81 Inorder(root);//中序遍历二叉链表算法 82 std::cout << " "; 83 } 84 85 void main2() 86 { 87 BinTNode *root; 88 BinTNode array[100]; 89 90 for (int i = 0; i < 100; i++) 91 { 92 array[i].data = i; 93 } 94 95 for (int i = 0; i < 99 / 2; i++) 96 { 97 array[i].lchild = &array[2 * i + 1]; 98 array[i].rchild = &array[2 * i + 2]; 99 } 100 101 root = &array[0]; 102 103 Preorder(root);//前序遍历二叉链表算法 104 } 105 106 void Preorder(BinTNode *bt)//前序遍历二叉链表算法 107 { 108 if (bt != NULL) 109 { 110 std::cout << bt->data << " "; 111 Preorder(bt->lchild); 112 Preorder(bt->rchild); 113 } 114 } 115 116 void Inorder(BinTNode *bt)//中序遍历二叉链表算法 117 { 118 if (bt != NULL) 119 { 120 Inorder(bt->lchild); 121 std::cout << bt->data << " "; 122 Inorder(bt->rchild); 123 } 124 } 125 126 void Postorder(BinTNode *bt)//后序遍历二叉链表算法 127 { 128 if (bt != NULL) 129 { 130 Postorder(bt->lchild); 131 Postorder(bt->rchild); 132 std::cout << bt->data << " "; 133 } 134 } 135 136 void Inorder1(BinTNode *bt)//利用栈的非递归中序遍历算法 137 { 138 std::stack<BinTNode *>S; 139 BinTNode *p; 140 S.push(bt); 141 142 while (!S.empty()) 143 { 144 while (S.top()) 145 { 146 S.push(S.top()->lchild);//直到左子树空为止 147 } 148 149 p = S.top(); 150 S.pop();//空指针退栈 151 152 if (!S.empty()) 153 { 154 std::cout << S.top()->data << " ";//访问根结点 155 156 p = S.top(); 157 S.pop(); 158 159 S.push(p->rchild);//右子树进栈 160 } 161 } 162 } 163 164 void Inorder2(BinTNode *bt)//用指针数组来实现二叉树非递归中序遍历算法 165 { 166 BinTNode *ST[100];//用指针数组模拟栈 167 int top = 0;//初始化数组 168 ST[top] = bt; 169 170 do 171 { 172 while (ST[top] != NULL)//根结点及其所有的左结点地址装入数组 173 { 174 top++; 175 ST[top] = ST[top - 1]->lchild; 176 } 177 top = top - 1; 178 if (top >= 0)//判数组中地址是否访问完 179 { 180 std::cout << ST[top]->data << " ";//访问结点 181 ST[top] = ST[top]->rchild;//扫描右子树 182 } 183 } while (top != -1); 184 } 185 186 int getyenum(BinTNode *bt)//统计叶子结点数量 187 { 188 int left = 0; 189 int right = 0; 190 if (!bt) 191 { 192 return 0; 193 } 194 if (!bt->lchild && !bt->rchild) 195 { 196 return 1; 197 } 198 left = getyenum(bt->lchild); 199 right = getyenum(bt->rchild); 200 return left + right; 201 } 202 203 int BinTreeDepth(BinTNode *bt)//二叉树的深度 204 { 205 int depl, depr; 206 if (!bt) 207 { 208 return 0; 209 } 210 else 211 { 212 depl = BinTreeDepth(bt->lchild); 213 depr = BinTreeDepth(bt->rchild); 214 if (depl > depr) 215 { 216 return depl + 1; 217 } 218 else 219 { 220 return depr + 1; 221 } 222 } 223 } 224 225 void TransLevel(BinTNode *bt)//按层遍历二叉树,从上到下,从左到右 226 { 227 std::queue<BinTNode *>myqueue; 228 if (!bt)//二叉树为空,返回 229 { 230 return; 231 232 } 233 else 234 { 235 std::cout << bt->data << " ";//输出根结点 236 myqueue.push(bt);//根结点指针入队 237 while (!myqueue.empty()) 238 { 239 bt = myqueue.front(); 240 myqueue.pop();//出队列 241 if (bt->lchild) 242 { 243 std::cout << bt->lchild->data << " ";//输出左子树根结点 244 myqueue.push(bt->lchild);//左子数入队列 245 } 246 if (bt->rchild) 247 { 248 std::cout << bt->rchild->data << " ";//输出右子树根结点 249 myqueue.push(bt->rchild);//右子数入队列 250 } 251 } 252 } 253 } 254 255 int getfather(BinTNode *bt, int num)//查找二叉树的父结点 256 { 257 if (!bt) 258 { 259 return 0; 260 } 261 if (bt->lchild && bt->lchild->data == num) 262 { 263 return bt->data; 264 } 265 if (bt->lchild && bt->rchild->data == num) 266 { 267 return bt->data; 268 } 269 getfather(bt->lchild, num); 270 getfather(bt->rchild, num); 271 } 272 273 int getleft(BinTNode *bt, int num)//查找二叉树的某个结点的左兄弟 274 { 275 if (!bt) 276 { 277 return 0; 278 } 279 if (bt->rchild && bt->rchild->data == num) 280 { 281 if (bt->lchild) 282 { 283 return bt->lchild->data; 284 } 285 } 286 getfather(bt->lchild, num); 287 getfather(bt->rchild, num); 288 } 289 290 int findmax(BinTNode *bt)//查找二叉树的最大值 291 { 292 BinTNode *ST[100];//用指针数组模拟栈 293 int top = 0;//初始化数组 294 ST[top] = bt; 295 int max = 0;//保存最大值 296 297 do 298 { 299 while (ST[top] != NULL)//根结点及其所有的左结点地址装入数组 300 { 301 top++; 302 ST[top] = ST[top - 1]->lchild; 303 } 304 top = top - 1; 305 if (top >= 0)//判数组中地址是否访问完 306 { 307 if (max < ST[top]->data) 308 { 309 max = ST[top]->data; 310 } 311 312 ST[top] = ST[top]->rchild;//扫描右子树 313 } 314 } while (top != -1); 315 316 return max; 317 } 318 319 BinTNode *insertnode(BinTNode *bt, int num)//二叉树插入 320 { 321 if (!bt) 322 { 323 BinTNode *pnew = new BinTNode; 324 pnew->data = num; 325 bt = pnew; 326 } 327 else if (num < bt->data) 328 { 329 bt->lchild = insertnode(bt->lchild, num); 330 } 331 else 332 { 333 bt->rchild = insertnode(bt->rchild, num); 334 } 335 336 return bt; 337 }
5.3.3二叉树的应用举例
已知二叉树的前序和中序遍历序列或中序和后序遍历序列,可以还原出原始的二叉树。
但是已知二叉树的前序和后序遍历序列,是无法还原出原始的二叉树。
前序遍历,最前面的是根结点。
后序遍历,最后面的是根结点。
应用
树是数据库中数据组织一种重要形式
操作系统子父进程的关系本身就是一棵树(进程树)
面向对象语言中类的继承关系本身就是一棵树
哈夫曼树