二叉树遍历的核心问题:二维结构(树)的线性化(线性序列)
- 从当前结点访问其左右儿子结点;
- 访问了左儿子后,如何访问右儿子?
需要一个存储结构保存暂时访问不到的结点(如右儿子或该结点自己)
存储结构:堆栈、队列
【二叉树的非递归遍历】
非递归算法实现的基本思路:利用堆栈
中序遍历非递归算法:
- 遇到一个结点,就将其压栈,并遍历其左子树;
- 当左子树遍历结束时,从栈顶弹出这个结点并访问它;
- 然后按其右指针再去中序遍历该结点的右子树。
序号 |
栈内元素
扫描二维码关注公众号,回复:
1118366 查看本文章
|
操作 |
输出序列 |
1 |
A |
PUSH |
NULL |
2 |
BA |
PUSH |
NULL |
3 |
DBA |
PUSH |
NULL |
4 |
BA |
POP |
D |
5 |
A |
POP |
DB |
6 |
FA |
PUSH |
DB |
7 |
EFA |
PUSH |
DB |
8 |
FA |
POP |
DBE |
9 |
A |
POP |
DBEF |
10 |
NULL |
POP |
DBEFA |
10 |
C |
PUSH |
DBEFA |
12 |
GC |
PUSH |
DBEFA |
13 |
C |
POP |
DBEFAG |
14 |
HC |
PUSH |
DBEFAG |
15 |
C |
POP |
DBEFAGH |
16 |
NULL |
POP |
DBEFAGHC |
17 |
I |
PUSH |
DBEFAGHC |
18 |
NULL |
POP |
DBEFAGHCI |
//中序遍历的非递归实现 void InOrderTraversal( BinTree BT){ BinTree T = BT; Stack S = CreatStack( MaxSize ); while( T || !IsEmpty(S)){ while(T){ Push(S,T); T = T->Left; } if(!IsEmpty(S)){ T = Pop(S); cout<<T->Data<<endl; T = T->Right; } } }
//先序遍历的非递归实现 void InOrderTraversal( BinTree BT){ BinTree T = BT; Stack S = CreatStack( MaxSize ); while( T || !IsEmpty(S)){ while(T){ Push(S,T); cout<<T->Data<<endl; T = T->Left; } if(!IsEmpty(S)){ T = Pop(S); T = T->Right; } } }
【层序遍历】
基本思路:利用队列
层序遍历算法:
- 从队列中取出一个元素;
- 访问该元素所指结点;
- 若该元素所指结点的左右儿子结点非空,则将其左右儿子的指针顺序入队。
序号 |
队列元素 |
输出序列 |
1 |
A |
NULL |
2 |
BC |
A |
3 |
CDF |
AB |
4 |
DFGI |
ABC |
5 |
FGI |
ABCD |
6 |
GIE |
ABCDF |
7 |
IEH |
ABCDFG |
8 |
EH |
ABCDFGI |
9 |
H |
ABCDFGIE |
10 |
NULL |
ABCDFGIEH |
void LevelOrderTraversal( BinTree BT) { Queue Q; BinTree T; if( !BT ) return; Q = CreatQueue( MaxSize ); AddQ( Q,BT ); while( !IsEmptyQ( Q )){ T = DeleteQ( Q ); cout<<T->Data<<endl; if( T->Left ) AddQ( Q,T->Left ); if( T->Right ) AddQ( Q,T->Right ); } }
【应用】
1.输出二叉树中的叶子结点
//在二叉树的遍历算法中增加检测结点的“左右子树是否都为空” void PreOrderPrintLeaves( BinTree BT ) { if( BT ){ if( !BT->Left && !BT->Right ) cout<<BT->Data<<endl; PreOrderPrintLeaves( BT->Left ); PreorderPrintLeaves( BT->Right ); } }
2.求二叉树的高度(Height=max(H1,H2)+1)
int PostOrderGetHeight( BinTree BT ) { int HL, HR, MaxH; if( BT ){ HL = PostOrderGetHeight( BT->Left ); HR = PostOrderGetHeight( BT->Right ); MaxH = ( HL > HR )? HL: HR; return ( MaxH+1 ); } else return 0; }
3.二元运算表达式树及其遍历
4.前/后序遍+中序遍历,可以唯一确定一棵树;但前序遍历+后序遍历不可唯一确定一棵树。
如上图,中序遍历可以将左右子树分隔开来。诶呦中序则无法确定左右,如下图: