先看一道例题:
先序遍历
若二叉树非空:
1)访问根结点
2)先序遍历左子树
3)先序遍历右子树
先序遍历的递归算法:
void Preorder (BiTree T){
if(T!=NULL){
visit(T);
Preorder(T->lchild);
Preorder(T->rchild) ;
)
}
先序遍历序列:124536
中序遍历
若二叉树非空:
1)中序遍历左子树
2)访问根结点
3)中序遍历右子树
中序遍历的递归算法:
void Inorder (BiTree T){
if(T!=NULL){
Inorder (T->lchild);
visit(T);
Inorder (T->rchild);
)
中序遍历序列:425163
后序遍历
若二叉树非空:
1)后序遍历左子树
2)后序遍历右子树
3)访问根结点
后序遍历算法:
void Postorder (BiTree T){
if(T!=NULL){
Postorder (T->lchild);
Postorder (T->rchild) ;
visit(T);
}
)
后序遍历序列:452631
中序遍历非递归算法
借助栈
算法思想:
1)初始时依次扫描根结点的所有左侧结点并将它们——进栈;
2)出栈一个结点,访问它;
3)扫描该结点的右孩子结点并将其进栈;
4)依次扫描右孩子结点的所有左侧结点并——进栈;
5)反复该过程直到栈空为止。
扫描根结点依次进栈,如下图:
出栈一个节点,并访问,如下图:
访问结点2
扫描结点2的右孩子并将其进栈,如下图:
弹出栈顶
扫描该结点的右孩子结点并将其进栈,如下图:
依次扫描右孩子结点的所有左侧结点并——进栈
弹出6结点
栈空
中序遍历序列:7425163
void Inorder2(BiTree T){
Initstack(S); BiTree p = T;
while(p||!ISEmpty(s)){
if (p){
Push(s,p);
p=p->lchild;
}
else{
Pop(s,p) ;visit(p);
p=p->rchild;
)
}
}
层次遍历
借助队列
算法思想:
1)初始将根入队并访问根结点;
2)若有左子树,则将左子树的根入队;
3)若有右子树,则将右子树的根入队;
4)然后出队,访问该结点;
5)反复该过程直到队列空为止。
初始将根入队并访问根结点,如下图:
出队并访问
有左子树,将左子树的根入队
有右子树,将右子树根入队
然后出队,并访问该结点。如下图,队首2出队
访问2
有左子树,根结点入队
此时有右子树,右子树入队
步骤3,出队,并访问该结点,此时队首是结点3,弹出3
此时有左子树,所以左子树的根入队,并且出队,队首4结点出队
访问结点4,并且此时有左子树,将左子树根入队,7入队,如下图
弹出队首5结点,并访问它
弹出队首6结点,并访问
弹出队首7结点,并访问
void levelOrder (BiTree T){
InitQueue(Q);
BiTree p;
EnQueue (Q,T);
while( !isEmpty(Q)){
DeQueue(Q, p);
visit(p);
if(p->lchild!=NULL)
EnQueue(Q,p->lchild);
if(p->rchild!=NULL)
EnQueue(Q,p->rchild);
}
}
由遍历序列构造二叉树
★(后)先序遍历序列和中序遍历序列可以确定一棵二叉树,
而后序遍历序列和先序遍历序列不可以确定一棵二叉树
中序遍历序列和先序遍历序列
1)在先序序列中,第一个节点是根结点;
2)根结点将中序遍历序列划分为两部分;
3)然后在先序序列中确定两部分的结点,并且两部分的第一个结点分别为左子树的根和右子树的根;
4)在子树中递归重复该过程,便能唯一确定一棵二叉树。
如下题:
先序序列第一个结点是根节点,那么就将序列分成左 425,右 63
然后,中序序列是425,中序的顺序是左中右,所以对应的就如下图, 且先序序列是中左右,正好符合先序序列245
中序序列63, 先左后中再右,所以 6是左,且先序顺序是36(中左右),所以3 是中位。