二叉树的遍历
对于二叉树的操作,大家可能会想到二叉树的三种遍历:先序遍历、中序遍历以及后序遍历。下面我们来讲述二叉树的这三种遍历,大约10-15分钟左右读完,希望大家找只笔和纸,手写一下!!!
一、先序遍历
1.先序遍历思想
(1)若二叉树为空,则为空操作,返回空
(2)访问根结点
(3)先序遍历左子树
(4)先序遍历右子树
- 先序遍历的递归算法
void PreOrderTraverse(BiTree BT) { if(BT) { printf("%c",BT->data); //访问根结点 PreOrderTraverse(BT->lchild); //前序遍历左子树 PreOrderTraverse(BT->rchild); //前序遍历右子树 } }
- 使用栈保存每个节点右子树的二叉树先序遍历的非递归算法
(1)当树为空时,将指针p指向根结点,p为当前结点指针
(2)先访问当前结点p,并将p压入栈中
(3)令p指向左孩子
(4)重复执行步骤(2)和(3),直到p为空为止
(5)从栈中弹出栈顶元素,将p指向此元素的右孩子
(6)重复执行步骤(2)~(5),直到p为空并且栈S也为空 ,最后结束遍历
void PreOrderNoRec(BiTree BT) { stack S; BiTree p=BT->root; while((NULL!=p)||!StackEmpty(S)) { if(NULL!=p) { printf("%c",p->data); Push(S,p); p=p->lchild; } else { p=Top(S); Pop(S); p=p->rchild; } } }
二、中序遍历
(1)若二叉树为空,则为空操作,返回空。
(2)中序遍历左子树。
(3)访问根结点。
(4)中序遍历右子树。
- 中序遍历的递归算法
void InOrderTraverse(BiTree BT) { if(BT) { InOrderTraverse(BT->lchild); //中序遍历左子树 printf("%c",BT->data); //访问根结点 InOrderTraverse(BT->rchild); //中序遍历右子树 } }
- 使用栈存储中序遍历的非递归算法
(1)当树为空时,将指针p指向根结点,p为当前结点指针。
(2)将p压入栈S中,并令p指向其左孩子。
(3)重复执行步骤(2),直到p为空。
(4)从栈S中弹出栈顶元素,将p指向此元素。
(5)访问当前结点p,并将p指向其右孩子。
(6)重复执行步骤(2)~(5),直到p为空并且栈S也为空。
(7)遍历结束。
void IneOrderNoRec(BiTree BT) { stack S; BiTree p=BT->root; while((NULL!=p)||!StackEmpty(S)) { if(NULL!=p) { Push(S,p); p=p->lchild; } else { p=Top(S); Pop(S); printf("%c",p->data); p=p->rchild; } } }
三、后序遍历
(1)若二叉树为空,则为空操作,返回空。
(2)后序遍历左子树。
(3)后序遍历右子树。
(4)访问根结点。
- 后序遍历的递归算法
void PostOrderTraverse(BiTree BT) { if(BT) { PostOrderTraverse(BT->lchild); //后序遍历左子树 PostOrderTraverse(BT->rchild); //后序遍历右子树 printf("%c",BT->data); //访问根结点 } }
- 使用栈来存储后序遍历的非递归算法
首先扫描根结点的所有左结点并入栈,然后出栈一个结点,扫描该结点的右结点并入栈,再扫描该右结点的所有左结点并入栈,当一个结点的左、右子树均被访问后再访问该结点。因为在递归算法中,左子树和右子树都进行了返回,因此为了区分这两种情况,还需要设置一个标识栈tag,当tag的栈顶元素为0时表示从左子树返回,为1表示从右子树返回。
(1)当树为空时,将指针p指向根结点,p为当前结点指针。
(2)将p压入栈S中,0压入栈tag中,并令p指向其左孩子。
(3)重复执行步骤(2),直到p为空。
(4)如果tag栈中的栈顶元素为1,跳至步骤(6)。
(5)如果tag栈中的栈顶元素为0,跳至步骤(7)。
(6)将栈S的栈顶元素弹出,并访问此结点,跳至步骤(8)。
(7)将p指向栈S的栈顶元素的右孩子。
(8)重复执行步骤(2)~(7),直到p为空并且栈S也为空。
(9)遍历结束。
void PostOrderNoRec(BiTree BT) { stack S; stack tag; BiTree p=BT->root; while((NULL!=p)||!StackEmpty(S)) { while(NULL!=p) { Push(S,p); Push(tag,0); p=p->lchild; } if(!StackEmpty(S)) { if(Pop(tag)==1) { p=Top(S); Pop(S); printf("%c",p->data); Pop(tag); //栈tag要与栈S同步 } else { p=Top(S); if(!StackEmpty(S)) { p=p->rchild; Pop(tag); Push(tag,1); } } } } }
以上就是二叉树对的遍历部分思想,希望可以对大家对二叉树遍历有所帮助