树在计算机领域应用广泛,尤以二叉树最为常用。如在操作系统中,用树来表示文件目录的组织结构,在编译系统中,用树来表示源程序的语法结构,在数据库系统中,数结构也是信息的重要组织形式之一。本文仅是本人学习二叉树遍历的学习记录,希望以此对树结构有深刻的理解。
注:四、五两部分用到的栈和队列的操作请看:
遍历二叉树分三种:先序遍历二叉树(根左右)、中序遍历二叉树(左根右)、后序遍历二叉树(左右根)。
一、三种遍历方式的操作定义
1、先序遍历二叉树的操作定义:
若二叉树为空,则空操作;否则
1)访问根结点;
2)先序遍历左子树;
3)先序遍历右子树;
2、中序遍历二叉树操作定义:
若二叉树为空,则空操作;否则
1)中序遍历左子树;
2)访问根结点;
3)中序遍历右子树。
3、后序遍历二叉树操作定义:
若二叉树为空,则空操作;否则
1)后序遍历左子树;
2)后序遍历右子树;
3)访问根结点。
用二叉树表示算术表达式:
先序序列:-+ab-cd/ef(前缀表示(波兰式))
中序遍历:a+bc-d-e/f(中缀表示)
后序遍历:abcd-*+ef/-(后缀表示(逆波兰式))
前缀表达式就是先进行符号运算,也叫波兰表示
中缀表达式就是我们平时所用的标准四则运算表达式
后缀表达式是一种不需要括号的后缀表达法,也称为逆波兰表示
利用二叉树可以将中缀表示转化为后缀表示。
二、根据遍历序列确定二叉树
- 若二叉树中各结点的值均不相同,则二叉树结点的先序序列、中序序列和后序序列都是唯一的
- 有二叉树的先序序列和中序序列,或由二叉树的后序序列和中序序列可以确定唯一 一颗二叉树
后序遍历,根结点必在后序序列尾部,所以先找到根:A,然后判断哪些在左子树上,哪些在右子树上,然后找到左子树的根:B,以此类推找根结点
但根据先序序列和后序序列无法确定二叉树
三、遍历的算法实现
1)先序遍历(根左右)
Status PreOrderTraverse(BiTree T){
if(T==NULL)
return OK;//空二叉树
else{
visit(T);//访问根结点,例如输出根节点cout<<T->data;
PreOrderTraverse(T->lchild);//递归遍历左子树
PreOrderTraverse(T->rchild);//递归遍历右子树
执行过程:设主程序为Pre(T)
void Pre(BiTree *T){
if(T!=NULL){
printf("%d\t",T->data);
pre(T->lchild);
pre(T->rchild);
}
}
2)中序遍历(左根右)
void InOrderTraverse(BiTree T)
{
if(T) //二叉树非空
{
InOrderTraverse(T->lchild);//递归遍历左子树
visit(T);//访问根结点,或写做cout<<T->data;
InOrderTraverse(T->rchild);//递归遍历右子树
}
}
3)后序遍历(左右根)
Status PostOrderTraverse(BITree T)
{
if(T){
PostOrderTraverse(T->lchild);
PostOrderTraverse(T->rchild);
cout<<T->data;
}
}
从虚线的出发点到终点的路径上,每个结点经过3次。
第一次经过时访问=先序遍历
第二次经过时访问=中序遍历
第三次经过时访问=后序遍历
时间复杂度O(n)//每个结点只访问一次
空间复杂度S(n)//栈占用的最大辅助空间。
四、中序遍历非递归算法(用栈实现)
二叉树中序遍历的非递归算法的关键:在中序遍历过某结点的整个左子树后,如何找到该结点根以及右子树。
基本思想:
(1)建立一个栈
(2)根结点进栈,遍历左子树,为空则根结点出栈。
(3)根结点出栈,输出根结点,遍历右子树。
Status InOrderTraverse(BiTree T)
{
BiTree p;
InitStack(S);
p=T;
while(p||!StackEmpty(S))
{
if(p)
{
Push(S,p);
p=p->lchild;
}
else
{
Pop(S,q);
cout<<q->data;
p=p->rchild;
}
return OK;
}
}
五、二叉树的层次遍历(队列实现)
对于一棵二叉树,从根结点开始,按从上到下、从左到右的顺序访问每一个结点,每个结点仅访问一次。
算法设计思路:使用一个队列
1、将根结点进队;
2、队不空时循环:从队列中出队一个结点*p,访问它;
- 若它有左孩子结点,将左孩子结点进队
- 若它有右孩子结点,将右孩子结点进队
也就是出队一个元素后,将它的左右孩子入队。
使用队列类型定义如下:
typedef struct{
BTNode data[MaxSize];//存放队中元素
int front,rear; //队头和队尾指针
}SqQueue; //顺序循环队列类型
二叉树层次遍历算法
void LevelOrder(BTNode *b)
{
BTNode *p;
SqQueue *qu;
InitQueue(qu); //初始化队列
enQueue(qu,b); //根结点指针进入队列
while(!QueueEmpty(qu)) //队不为空,则循环
{
deQueue(qu,p); //出对结点p
cout<<p->data; //访问结点p
if(p->lchild!=NULL)
enQueue(qu,p->lchild);//有左孩子时将其进队
if(p->rchild!=NULL)
enQueue(qu,p->rchild);//有右孩子时将其进队
}
}
//所有元素出队后,程序结束
内容参考:《数据结构》严蔚敏