文章目录
- 1 先序遍历
- 1.1 先序遍历递归
- 1.2 先序遍历非递归
- 2 中序遍历
- 2.1 中序遍历递归
- 2.2 中序遍历非递归
- 3 后序遍历
- 3.1 后序遍历递归
- 3.2 后序遍历非递归
- 4 层序遍历
1 先序遍历
若二叉树为空,则操作返回,否则先访问根结点,然后前序遍历左子树,再前序遍历右子树
1.1 先序遍历递归
void PreviousOrderTraverse(BTNode T) {if (T == NULL) {return;}/* 对节点的操作 */PreviousOrderTraverse(T->lchild); // 先序遍历左子树PreviousOrderTraverse(T->rchild); // 再先序遍历右子树
}
1.2 先序遍历非递归
递归的实现依赖于栈,那么就将二叉树的递归遍历转换为非递归遍历,也就是利用栈来实现
void PreviousOrderTraverse(BTNode *bt)
{if(bt !=NULL){BTNode *Stack[maxSize]; int top=-1;BTNode *p=NULL; //p为遍历指针Stack[++top]=bt;while(top!=-1){p=Stack[top--]; //根结点出栈并访问visit(p);if(p->rchild!=NULL)//检测左右孩子是否存在Stack[++top]=p->rchild; //先入if(p->rchild!=NULL)Stack[++top]=p->lchild;}}
}
2 中序遍历
若二叉树为空,则操作返回,否则从根节点开始(注意不是先访问根结点),中序遍历根结点的左子树,然后是访问根结点,最后中序遍历右子树
2.1 中序遍历递归
void InOrderTraverse(BTNode T) {if (T == NULL) {return;}InOrderTraverse(T->lchild); // 先中序遍历左子树/* 对结点的操作 */InOrderTraverse(T->rchild); // 再中序遍历右子树
}
2.2 中序遍历非递归
void InOrderTraverse(BTNode *bt)
{BTNode p = T; // p 是遍历指针Stack S = CreateStack(MAXSIZE); // 初始化栈while (p != NULL || !IsEmpty(S)) { // 栈不为空或 p 不为空时遍历if (p != NULL) {Push(S, p); // 一直向左并将沿途节点压入堆栈p= p->leftChild;} else { // p 为空时,栈不为空,弹出节点访问右孩子p= Pop(S); // 弹出堆栈visit();//访问节点p = p->rightChild;}}
}
3 后序遍历
若二叉树为空,则操作返回,否则从左到右,先叶子后结点的方式遍历访问左右子树,最后是访问根结点
3.1 后序遍历递归
void PostOrderTraverse(BTNode T) {if (T == NULL) {return;}PostOrderTraverse(T->lchild); // 先后序遍历左子树PostOrderTraverse(T->rchild); // 再后序遍历右子树/* 对结点的操作 */
}
3.2 后序遍历非递归
- 后序非递归遍历二叉树的顺序是先访问左子树,再访问右子树,最后访问根结点。当用堆栈存储结点时,必须分清返回根结点时是从左子树返回还是从右子树返回的;因此,必须使用辅助指针指向最近访问过的结点。
void PostOrderTraverse(BTNode T) {BTNode p = T; // p 为遍历指针BTNode pTop = NULL; // pTop 为临时指针BTNode pLast = NULL; // pLast 为保存已访问节点指针Stack S = CreateStack(MAXSIZE); // 初始化栈while (p != NULL || !IsEmpty(S)) { // 栈不为空或 p 不为空时遍历 while (p != NULL) {Push(s, p); // 一直向左并将沿途节点压入堆栈 p = p->lchild;}pTop = GetStackTop(s); // 取栈顶元素,不是出栈//当栈顶元素的右孩子为空,或者为已经遍历过的节点if (pTop->rchild == NULL || pTop->rchild == pLast) {StackPop(s); // 出栈,打印,并令遍历过的节点为此时的栈顶元素visit();//访问节点pLast = pTop; // 将 pTop 设为已经遍历过的节点 continue; // 继续循环}p = pTop->rchild; //遍历它的右孩子}
}
- 在先序遍历非递归上进行修改,先进左孩子,再进右孩子得逆后序序列,再借助一个栈将逆后序序列转化为后序序列
void PostorderTraverse(BTNode *bt)
{if(bt!=NULL){/*定义两个栈*/BTNode *Stack1[maxSize]; int top1=-1; //遍历栈 BTNode *Stack2[maxSize]; int top2=-1; //结果序列逆序的栈BTNode *p=NULL;Stack1[++top1]=bt;while(top1!=NULL){p=Stack1[top1--];Stack2[++top2]=p; //每次1出栈,便进2栈 /* 以下与先序遍历区别:左右孩子入栈顺序相反*/if(p->lchild!=NULL)Stack1[++top1]=p->lchild;if(p->rchild!=NULL)Stack1[++top1]=p->rchild; }while(top2!=-1){/*出栈序列即为后序遍历序列*/p=Stack2[top2--];visit(p); //visit是访问p的函数,此处执行打印结点值操作 }}
}
4 层序遍历
若二叉树为空,则操作返回,否则从树的第一层,也就是根结点开始访问,从上而下逐层遍历,在同一层中,按从左到右的顺序对结点逐个访问
- 根结点入队
- 从队列中取出一个元素
- 访问该元素所指的结点
- 若该元素所指结点的左右孩子为非空,则将其左、右孩子的指针顺序入队
void LevelTraverse(BTNode *bt)
{if(bt!=NULL) //根结点不空即树不空 {int front,rear;BTNode *que[maxSize];front=rear=0;BTNode *p; //p是遍历指针 rear=(rear+1)%maxSize;que[rear]=bt; //根结点入队 while(front!=rear) //队列为空则遍历结束 {front=(front+1)%maxSize;p=que[front];visit(p);if(p->lchild!=NULL){rear=(rear+1)%maxSize;que[rear]=p->lchild; //如果左子树不空,则入队 } if(p->rchild!=NULL){rear=(rear+1)%maxSize;que[rear]=p->rchild; //如果右子树不空,则入队 } }}
}