MOOC浙大数据结构-二叉树的遍历
二叉树的遍历前序遍历遍历过程:访问根节点中序遍历其左子树中序遍历其右子树void InOrderTraversal(BinTree BT){if (BT) {printf("%d", BT->Data);InOrderTraversal(BT->Left);InOrderTraversal(BT->Right);}}非递归遍历算法使用堆栈void InOrderTraversal
本文是MOOC浙大数据结构课程的笔记
课程详细地址
二叉树的遍历
前序遍历
遍历过程:
- 访问根节点
- 中序遍历其左子树
- 中序遍历其右子树
void InOrderTraversal(BinTree BT)
{
if (BT) {
printf("%d", BT->Data);
InOrderTraversal(BT->Left);
InOrderTraversal(BT->Right);
}
}
非递归遍历算法
使用堆栈
void InOrderTraversal(BinTree BT)
{
BinTree T = BT;
Stack S = CreatStack(MaxSize); //创建初始化堆栈s
while (T || !IsEmpty(s)) {
while (T) {// 一直向左并且将沿途的结点压入堆栈
Push(S, T);
printf("%5d", T->Data);// 打印结点
T = T->Left;
}
if (!IsEmpty(s)) {
T = Pop(s); // 结点弹出堆栈
T = T->Right;// 转向右子树
}
}
}
中序遍历
遍历过程:
- 中序遍历其左子树
- 访问根节点
- 中序遍历其右子树
递归
void InOrderTraversal(BinTree BT)
{
if (BT) {
InOrderTraversal(BT->Left);
printf("%d", BT->Data);
InOrderTraversal(BT->Right);
}
}
非递归遍历算法
使用堆栈
void InOrderTraversal(BinTree BT)
{
BinTree T = BT;
Stack S = CreatStack(MaxSize); //创建初始化堆栈s
while (T || !IsEmpty(s)) {
while (T) {// 一直向左并且将沿途的结点压入堆栈
Push(S, T);
T = T->Left;
}
if (!IsEmpty(s)) {
T = Pop(s); // 结点弹出堆栈
printf("%5d", T->Data);// 打印结点
T = T->Right;// 转向右子树
}
}
}
给出下面这棵树的中序遍历结果:
答:bdaec
后序遍历
遍历过程:
- 中序遍历其左子树
- 中序遍历其右子树
- 访问根节点
void InOrderTraversal(BinTree BT)
{
if (BT) {
InOrderTraversal(BT->Left);
InOrderTraversal(BT->Right);
printf("%d", BT->Data);
}
}
非递归遍历算法
使用堆栈
后序遍历也可以使用非递归遍历算法来实现,但不能像前序和中序一样简单的调一下输出语句就可以实现,因为后序遍历需要先访问完左右结点才输出根节点。
需要在结构中定义个标识
void InOrderTraversal(BinTree BT)
{
BinTree T = BT;
Stack S = CreatStack(MaxSize); //创建初始化堆栈s
while (T || !IsEmpty(s)) {
while (T) {// 一直向左并且将沿途的结点压入堆栈
Push(S, T);
T->Tag=1;// 标记为1
T = T->Left;
}
if (!IsEmpty(s)) {
T = Pop(s); // 结点弹出堆栈
if(T->Tag=1){
(T->Tag)++;
printf("%5d", T->Data);// 打印结点
T = T->Right;// 转向右子树
}else{
printf("%5d", T->Data);// 打印结点
}
}
}
}
层序遍历
二叉树遍历的核心问题:二维结构的线性化
- 从结点访问其左、右儿子结点
- 访问左儿子后、右儿子怎么办?
所以需要一个存储结构来保存暂时不访问的结点,可以用堆栈、队列来存储
队列实现:
遍历从根结点开始,首先将根结点入队,然后开始执行循环:结点出队、访问该结点、其左右儿子入队
遍历过程:
先根节点入队,然后:
- 从队列中取出一个元素;
- 访问该结点所指结点,
- 若该元素所指结点的左、右孩子结点非空,则将其左、右孩子的指针顺序入队。
void LevelOrderTraversal(BinTree BT)
{
Queue Q;BinTree T;
if(!BT)return; // 空树直接返回
Q=CreatQueue(MaxSize); // 创建队列
AddQ(Q,BT);
while(!IsEmptyQ(Q)){
T=DeleteQ(Q);
printf("%d\n",T->Data);
if(T->Left)AddQ(Q,T->Left);
if(T->Right)AddQ(Q,T->Right);
}
}
如果将层序遍历中的队列改为堆栈,是否也是一种树的遍历?可以应用这种方法改造出一种前序、中序、后序的非递归遍历吗?
上文已有解答。
遍历二叉树应用
🚩 输出二叉树中的叶子结点
void PreOrderPrintLeaves(BinTree BT)
{
if (BT) {
if(!BT->Left && !BT->Right)
printf("%d", BT->Data);
InOrderTraversal(BT->Left);
InOrderTraversal(BT->Right);
}
}
🚩 求二叉树的高度
只要知道了左右子树的高度就可以知道二叉树的高度
void PostOrderGetHeight(BinTree BT)
{
int HL,HR,MaxH;
if (BT) {
HL=PostOrderGetHeight(BT->Left);
HR=PostOrderGetHeight(BT->Right);
MaxH=(HL>HR)?HL:HR;
return (MaxH+1);
}
else return 0;
}
🚩 二元运算表达式树及其遍历

🚩两种遍历确定二叉树?
一定要有中序,没有中序会产生左右判断的问题
先序和中序遍历序列来确定一颗二叉树
- 根据先序遍历序列第一个结点确定根结点
- 根据根结点在中序遍历序列中分割出左右两个子序列
- 对左子树和右子树分别递归使用相同方法继续分解。

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐




所有评论(0)