2.3二叉树的遍历
树的表示
1 //树的表示 2 typedef struct TreeNode *BinTree; 3 struct TreeNode 4 { 5 int Data;//存值 6 BinTree Left;//左儿子结点 7 BinTree Right;//右儿子结点 8 };
2.3.1先序
- 先访问根结点
- 先序遍历其左子树
- 先序遍历其右子树
1 //先序遍历 递归实现 2 void PreOrderTraversal(BinTree BT) { 3 if (BT) { 4 printf("%d", BT->Data);//首次遇到即访问 5 PreOrderTraversal(BT->Left); 6 PreOrderTraversal(BT->Right); 7 } 8 }
1 //先序遍历 非递归实现 2 void PreOrderTraversal(BinTree BT) { 3 BinTree T = BT; 4 Stack S = CreatStack();//创建并初始化堆栈 5 while(T||!IsEmpty(S)){ 6 while (T) {//当树不为空的时候 7 printf("%d", T->Data);//第一次遇见就访问输出 8 Push(S, T); 9 T = T->Left;//遍历左子树 10 } 11 if (!IsEmpty(S)) { 12 T = Pop(S);//已经访问过了直接弹出 13 T = T->Right; 14 } 15 } 16 }
2.3.2中序
- 中序遍历其左子树
- 访问根结点
- 中序遍历其右子树
遍历结果:(DBEF)A(GHCI)
1 //中序遍历 递归实现 2 void InOrderTraversal(BinTree BT) { 3 if (BT) { 4 InOrderTraversal(BT->Left); 5 printf("%d", BT->Data); 6 InOrderTraversal(BT->Right); 7 } 8 }
1 //中序遍历 非递归 与中序遍历作比较只有printf("%d", T->Data)的位置不同 2 void InOrderTraversal(BinTree BT) { 3 BinTree T = BT; 4 Stack S = CreatStack(); 5 while (T || !IsEmpty(S)) { 6 while (T) 7 { 8 Push(S, T);//第一次遇到的时候不访问,将其压入堆栈 9 T = T->Left; 10 } 11 if (!IsEmpty(S)) { 12 T = Pop(S); 13 printf("%d", T->Data);//第二次遇到的时候访问 14 T = T->Right; 15 } 16 } 17 }
2.3.3后序
- 后序遍历其左子树
- 后序遍历其右子树
- 访问根结点
遍历结果:(DEFB)(HGIC)A
1 //后序遍历 递归实现 2 void PostOrderTraversal(BinTree BT) { 3 PostOrderTraversal(BT->Left); 4 PostOrderTraversal(BT->Right); 5 printf("%d", BT->Data); 6 }
1 //后序遍历非递归实现 2 void PostOrderTraversal(BinTree BT) { 3 BinTree T = BT; 4 Stack S = CreatStack(); 5 vector<BinTree>v; 6 Push(S, T); 7 while (!IsEmpty(S)){ 8 T = Pop(S); 9 v.push_back(T); 10 if (T->Left) 11 Push(S, T->Left); 12 if (T->Right) 13 Push(S, T->Right); 14 } 15 reverse(v.begin(), v.end());//进行翻转 因为出栈入动态数组的时候是先右后左 16 for (int i = 0; i < v.size(); i++) 17 printf("%d", v[i]->Data); 18 return 0; 19 }
归纳:
- 以上三种遍历过程中经过结点的路线一样,只是访问各结点的时机不同。
- 由两种遍历结果可知树的结构,前提是两种之一必须是中序遍历。
- 二叉树遍历的核心问题:二维结构的线性化
2.3.4层序遍历
用队列实现层序遍历:将根结点入队,将根结点出队,然后将根结点的左右儿子入队。
遍历结果:ABCDFGIFH
1 //层序遍历 使用队列 2 void LevelOrderTraversal(BinTree BT) { 3 Queue Q = CreatQueue(); 4 BinTree T; 5 if (!BT) { 6 return;//如果树空则返回 7 } 8 AddQ(Q, BT); 9 while (!IsEmpty(Q)) 10 { 11 T = DeleteQ(Q); 12 printf("%d", T->Data); 13 if (T->Left)AddQ(Q, T->Left); 14 if (T->Right)AddQ(Q, T->Right); 15 } 16 }