电脑故障

位置:IT落伍者 >> 电脑故障 >> 浏览文章

二叉树的遍历


发布日期:2018/11/6
 

遍历概念

所谓遍历(Traversal)是指沿着某条搜索路线依次对树中每个结点均做一次且仅做一次访问访问结点所做的操作依赖于具体的应用问题

遍历是二叉树上最重要的运算之一是二叉树上进行其它运算之基础

遍历方案

.遍历方案

从二叉树的递归定义可知一棵非空的二叉树由根结点及左右子树这三个基本部分组成因此在任一给定结点上可以按某种次序执行三个操作

)访问结点本身(N)

)遍历该结点的左子树(L)

)遍历该结点的右子树(R)

以上三种操作有六种执行次序

NLRLNRLRNNRLRNLRLN

注意

前三种次序与后三种次序对称故只讨论先左后右的前三种次序

.三种遍历的命名

根据访问结点操作发生位置命名

① NLR前序遍历(PreorderTraversal亦称(先序遍历))

——访问结点的操作发生在遍历其左右子树之前

② LNR中序遍历(InorderTraversal)

——访问结点的操作发生在遍历其左右子树之中(间)

③ LRN后序遍历(PostorderTraversal)

——访问结点的操作发生在遍历其左右子树之后

注意

由于被访问的结点必是某子树的根所以N(Node)L(Left subtlee)和R(Right subtree)又可解释为根根的左子树和根的右子树NLRLNR和LRN分别又称为先根遍历中根遍历和后根遍历

遍历算法

.中序遍历的递归算法定义

若二叉树非空则依次执行如下操作

()遍历左子树

()访问根结点

()遍历右子树

.先序遍历的递归算法定义

若二叉树非空则依次执行如下操作

() 访问根结点

() 遍历左子树

() 遍历右子树

.后序遍历得递归算法定义

若二叉树非空则依次执行如下操作

()遍历左子树

()遍历右子树

()访问根结点

.中序遍历的算法实现

用二叉链表做为存储结构中序遍历算法可描述为

void InOrder(BinTree T)

{ //算法里①~⑥是为了说明执行过程加入的标号

① if(T) { // 如果二叉树非空

② InOrder(T>lchild)

③ printf(%cT>data) // 访问结点

④ InOrder(T>rchild);

⑤ }

⑥ } // InOrder

遍历序列

.遍历二叉树的执行蹤迹

三种递归遍历算法的搜索路线相同(如下图虚线所示)

具体线路为

从根结点出发逆时针沿着二叉树外缘移动对每个结点均途径三次最后回到根结点

.遍历序列

) 中序序列

中序遍历二叉树时对结点的访问次序为中序序列

【例】中序遍历上图所示的二叉树时得到的中序序列为

D B A E C F

) 先序序列

先序遍历二叉树时对结点的访问次序为先序序列

【例】先序遍历上图所示的二叉树时得到的先序序列为

A B D C E F

) 后序序列

后序遍历二叉树时对结点的访问次序为后序序列

【例】后序遍历上图所示的二叉树时得到的后序序列为

D B E F C A

注意

) 在搜索路线中若访问结点均是第一次经过结点时进行的则是前序遍历若访问结点均是在第二次(或第三次)经过结点时进行的则是中序遍历(或后序遍历)只要将搜索路线上所有在第一次第二次和第三次经过的结点分别列表即可分别得到该二叉树的前序序列中序序列和后序序列

) 上述三种序列都是线性序列有且仅有一个开始结点和一个终端结点其余结点都有且仅有一个前趋结点和一个后继结点为了区别于树形结构中前趋(即双亲)结点和后继(即孩子)结点的概念对上述三种线性序列要在某结点的前趋和后继之前冠以其遍历次序名称

【例】上图所示的二叉树中结点C其前序前趋结点是D前序后继结点是E中序前趋结点是E中序后继结点是F后序前趋结点是F后序后继结点是A但是就该树的逻辑结构而言C的前趋结点是A后继结点是E和F

二叉链表的构造

. 基本思想

基于先序遍历的构造即以二叉树的先序序列为输入构造

注意

先序序列中必须加入虚结点以示空指针的位置

【例】

建立上图所示二叉树其输入的先序序列是ABD∮∮CE∮∮F∮∮

. 构造算法

假设虚结点输入时以空格字符表示相应的构造算法为

void CreateBinTree (BinTree *T)

{ //构造二叉链表T是指向根指针的指针故修改*T就修改了实参(根指针)本身

char ch

if((ch=getchar())==) *T=NULL //读人空格将相应指针置空

else{ //读人非空格

*T=(BinTNode *)malloc(sizeof(BinTNode)) //生成结点

(*T)>data=ch

CreateBinTree(&(*T)>lchild) //构造左子树

CreateBinTree(&(*T)>rchild) //构造右子树

}

}

注意

调用该算法时应将待建立的二叉链表的根指针的地址作为实参

【例】设root是一根指针(即它的类型是BinTree)则调用CreateBinTree(&root)后root就指向了已构造好的二叉链表的根结点

构造二叉链表的其他方法【参见参考书目】

二叉树建立过程见【动画演示】

二叉树的应用

【参见练习】

上一篇:出栈序列的研究[5]

下一篇:栈的定义及基本运算