数据结构34:二叉树前序遍历、中序遍历和后序遍历
鏈式存儲結(jié)構(gòu)存儲的二叉樹,對樹中結(jié)點進行逐個遍歷時,由于是非線性結(jié)構(gòu),需要找到一種合適的方式遍歷樹中的每個結(jié)點。
遞歸思想遍歷二叉樹
之前講過,樹是由根結(jié)點和子樹部分構(gòu)建的,對于每一棵樹來說,都可以分為 3 部分:左子樹、根結(jié)點和右子樹。所以,可以采用遞歸的思想依次遍歷每個結(jié)點。
根據(jù)訪問結(jié)點時機的不同,分為三種遍歷方式:
- 先訪問根結(jié)點,再遍歷左右子樹,稱為“先序遍歷”;
- 遍歷左子樹,之后訪問根結(jié)點,然后遍歷右子樹,稱為“中序遍歷”;
- 遍歷完左右子樹,再訪問根結(jié)點,稱為“后序遍歷”。
圖1 二叉樹
三種方式唯一的不同就是訪問結(jié)點時機的不同,給出一個二叉樹,首先需要搞清楚三種遍歷方式下訪問結(jié)點的順序。
圖2 二叉樹遍歷示意圖
圖2 中,箭頭線條的走勢為遍歷結(jié)點的過程:
先序遍歷是只要線條走到該結(jié)點的左方位置時,就操作該結(jié)點。所以操作結(jié)點的順序為:
中序遍歷是當(dāng)線條越過結(jié)點的左子樹,到達該結(jié)點的正下方時,才操作該結(jié)點。所以操作結(jié)點的順序為:
后序遍歷是線條完全走過結(jié)點的左右子樹,到達該結(jié)點的右方范圍時,就開始操作該結(jié)點。所以操作結(jié)點的順序為:
三種遍歷方式的完整代碼實現(xiàn)
#include <stdio.h> #include <string.h> #define TElemType int //構(gòu)造結(jié)點的結(jié)構(gòu)體 typedef struct BiTNode{TElemType data; //數(shù)據(jù)域struct BiTNode *lchild, *rchild; //左右孩子指針 }BiTNode, *BiTree;
//初始化樹的函數(shù) void CreateBiTree(BiTree *T)
{*T = (BiTNode*)malloc(sizeof(BiTNode));(*T)->data = 1;(*T)->lchild = (BiTNode*)malloc(sizeof(BiTNode));(*T)->rchild = (BiTNode*)malloc(sizeof(BiTNode));(*T)->lchild->data = 2;(*T)->lchild->lchild = (BiTNode*)malloc(sizeof(BiTNode));(*T)->lchild->rchild = (BiTNode*)malloc(sizeof(BiTNode));(*T)->lchild->rchild->data = 5;(*T)->lchild->rchild->lchild = NULL;(*T)->lchild->rchild->rchild = NULL;(*T)->rchild->data = 3;(*T)->rchild->lchild = (BiTNode*)malloc(sizeof(BiTNode));(*T)->rchild->lchild->data = 6;(*T)->rchild->lchild->lchild = NULL;(*T)->rchild->lchild->rchild = NULL;(*T)->rchild->rchild = (BiTNode*)malloc(sizeof(BiTNode));(*T)->rchild->rchild->data = 7;(*T)->rchild->rchild->lchild = NULL;(*T)->rchild->rchild->rchild = NULL;(*T)->lchild->lchild->data = 4;(*T)->lchild->lchild->lchild = NULL;(*T)->lchild->lchild->rchild = NULL; }
//模擬操作結(jié)點元素的函數(shù),輸出結(jié)點本身的數(shù)值 void displayElem(BiTNode* elem)
{printf("%d ", elem->data); }
//先序遍歷 void PreOrderTraverse(BiTree T)
{if (T)
{displayElem(T);//調(diào)用操作結(jié)點數(shù)據(jù)的函數(shù)方法PreOrderTraverse(T->lchild);//訪問該結(jié)點的左孩子PreOrderTraverse(T->rchild);//訪問該結(jié)點的右孩子}//如果結(jié)點為空,返回上一層return; }
//中序遍歷 void INOrderTraverse(BiTree T)
{if (T)
{INOrderTraverse(T->lchild);//遍歷左孩子displayElem(T);//調(diào)用操作結(jié)點數(shù)據(jù)的函數(shù)方法INOrderTraverse(T->rchild);//遍歷右孩子}//如果結(jié)點為空,返回上一層
return; }
//后序遍歷 void PostOrderTraverse(BiTree T)
{if (T)
{PostOrderTraverse(T->lchild); //遍歷左孩子PostOrderTraverse(T->rchild); //遍歷右孩子displayElem(T); //調(diào)用操作結(jié)點數(shù)據(jù)的函數(shù)方法}
//如果結(jié)點為空,返回上一層return; }
int main()
{BiTree Tree;CreateBiTree(&Tree);printf("前序遍歷: \n");PreOrderTraverse(Tree);printf("\n中序遍歷算法: \n");INOrderTraverse(Tree);printf("\n后序遍歷: \n");PostOrderTraverse(Tree); }
運行結(jié)果: 前序遍歷: 1 2 4 5 3 6 7 中序遍歷算法: 4 2 5 1 6 3 7 后序遍歷: 4 5 2 6 7 3 1
?
總結(jié)
由于二叉樹就是由根結(jié)點和左右子樹構(gòu)成的,所以很容易想到使用遞歸的思想。而遞歸算法的低層實現(xiàn)實際上使用的是棧的數(shù)據(jù)結(jié)構(gòu),所以二叉樹的先序、中序和后序遍歷同樣可以使用非遞歸的算法實現(xiàn)。
非遞歸算法的具體實現(xiàn)可以查看下一節(jié)的內(nèi)容。
轉(zhuǎn)載于:https://www.cnblogs.com/ciyeer/p/9044259.html
總結(jié)
以上是生活随笔為你收集整理的数据结构34:二叉树前序遍历、中序遍历和后序遍历的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 为何赵国在战争的生死存亡之际
- 下一篇: logback的使用和logback.x