1 概述
- 二叉树的遍历按遍历顺序有先序遍历、中序遍历、后序遍历、层次遍历四种,先序、中序和后序遍历可以通过递归或非递归的方式实现 。
- 递归算法实现简单,而非递归算法的执行效率要高于递归算法,借助栈,可以将二叉树的递归遍历算法转换为非递归算法,其中后序遍历的非递归算法较为复杂。
- 层次遍历需要借助队列实现。
- 讨论的二叉树采用二叉链表存储结构。
- 算法中的 visit 函数对结点进行访问,“ 访问 ” 的含义很广,可以是对结点作各种处理,如输出结点的信息等。
2 选用策略
求根结点到某结点的路径、求两个结点的最近公共祖先可选用后序遍历。
用层次遍历易于找到某结点的父结点。
3 递归算法
3.1 先序遍历
void PreOrderTraverse(BiTree T){
if (T){
visit(T);
PreOrderTraverse(T->lchild);
PreOrderTraverse(T->rchild);
}
}
3.2 中序遍历
void InOrderTraverse(BiTree T){
if (T){
InOrderTraverse(T->lchild);
visit(T);
InOrderTraverse(T->rchild);
}
}
3.3 后序遍历
void PostOrderTraverse(BiTree T){
if (T){
PostOrderTraverse(T->lchild);
PostOrderTraverse(T->rchild);
visit(T);
}
}
4 非递归算法
4.1 先序遍历
void PreOrderTraverse(BiTree T){
InitStack(S); //初始化栈
BiTree p = T; //p是遍历指针
while (p || !IsEmpty(S)){ //p不空或栈不空时循环
if (p){
visit(p); //访问该结点
Push(S, p); //指针进栈
p = p->lchild; //向左走
}
else{
Pop(S, p); //指针出栈
p = p->rchild; //向右走
}
}
}
4.2 中序遍历
void InOrderTraverse(BiTree T){
InitStack(S); //初始化栈
BiTree p = T; //p是遍历指针
while (p || !IsEmpty(S)){ //p不空或栈不空时循环
if (p){
Push(S, p); //指针进栈
p = p->lchild; //向左走
}
else{
Pop(S, p); //指针出栈
visit(p); //访问该结点
p = p->rchild; //向右走
}
}
}
4.3 后序遍历
void PostOrderTraverse(BiTree T){
InitStack(S); //初始化栈
BiTree p = T; //遍历指针
BiTree r = NULL; //辅助指针,指向最近访问过的结点,用于在返回根结点时区分右子树是否已经访问过
while (p || IsEmpty(S)){
if (p){
Push(S, p);
p = p->lchild;
}
else{
GetTop(S, p); //取栈顶结点
if (p->rchild && p->rchild!=r){
p = p->rchild;
Push(S, p);
p = p->lchild;
}
else{
Pop(S, p);
visit(p);
r = p;
p = NULL;
}
}
}
}
4.4 层次遍历
void LevelOrderTraverse(BiTree T){
InitQueue(Q); //初始化队列
BiTree p;
EnQueue(Q, T); //将根结点入队
while (!IsEmpty(Q)){
DeQueue(Q, p); //队头元素出队
visit(p);
if (p->lchild){
EnQueue(Q, p->lchild); //其左子结点入队
}
if (p->rchild){
EnQueue(Q, p->rchild); //其右子结点入队
}
}
}