遍歷二叉樹
- 遍歷定義:順着某一條搜索路徑巡防二叉樹中的結點,使得每個結點均被訪問一次,而且僅被訪問一次(又稱周遊)。
- 遍歷目的:得到樹中所有結點得一個線性排列。
- 遍歷用途:它是樹結構插入、刪除、修改、查找和排序運算得前提,是二叉樹一切運算得基礎和核心。
- 遍歷方法:
依次遍歷二叉樹中的三個組成部分,便是遍歷了整個二叉樹
假設:L:遍歷左子樹 D:訪問根結點 R:遍歷右子樹
則遍歷整個二叉樹方案共有:
DLR、LDR、LRD、DRL、RDL、RLD六種。
1.遍歷二叉樹遞歸算法描述
若規定先左後右,則只有前三種情況:
DLR ——先(根)序遍歷
LDR——中(根)序遍歷
LRD——後(根)序遍歷
先序遍歷二叉樹的操作定義
- 若二叉樹爲空,則空操作;否則:
1.訪問根結點(D);
2.先序遍歷左子樹(L);
3.先序遍歷右子樹(R)。
Status PreOrderTraverse(BiTree T)
{
if(T==NULL) return OK; //空二叉樹
else{
cout << T->data; //訪問根結點
PreOrderTraverse(T->lchild); //先序遍歷左子樹
PreOrderTraverse(T->rchild); //先序遍歷右子樹
}
}
中序遍歷二叉樹的操作定義
- 若二叉樹爲空,則空操作;否則
1.中序遍歷左子樹(L);
2.訪問根結點(D);
3.中序遍歷右子樹(R)。
Status InOrderTraverse(BiTree T)
{
if(T==NULL) return OK;
else{
InOrderTraverse(T->lchild); //中序遍歷左子樹
cout << T->data; //訪問根結點
InOrderTraverse(T->rchild); //中序遍歷右子樹
}
}
後序遍歷二叉樹的操作定義
- 若二叉樹爲空,則空操作;否則
1.後序遍歷左子樹;
2.後序遍歷右子樹;
3.訪問根結點。
Status PostOrderTraverse(BiTree T)
{
if(T==NULL) return OK;
else{
PostOrderTraverse(T->lchild); //後序遍歷左子樹
PostOrderTraverse(T->rchild); //後序遍歷右子樹
cout << T->data; //訪問根結點
}
}
遍歷算法的分析
- 如果去掉輸出語句,從遞歸的角度看,三種算法是完全相同的,或說這三種算法的訪問路徑是相同的,只是訪問結點的時機不同。
從虛線的出發點到終點的路徑上,每個結點經過3次。
- 時間效率:O(n) //每個結點只訪問一次
- 空間效率:O(n) //棧佔用的最大輔助空間
2.中序非遞歸算法描述
基本思想:
1.建立一個棧
2.根結點進棧,遍歷左子樹
3.根結點出棧,輸出根結點,遍歷右子樹。
【算法步驟】
①初始化一個空棧 S,指針 p 指向根結點
②申請一個結點空間 q,用來存放棧頂彈出的元素
③當 p 非空或者棧 S 非空時,循環執行以下操作:
如果 p 非空,則將 p 進棧,p指向該結點的左孩子
如果 p 爲空,則彈出棧頂元素並訪問,將p指向該結點的右孩子
【算法描述】
Status InOrderTraverse(BiTree T)
{
BiTree p; InitStack(S); p=T;
while(p || !StackEmpty(S))
{
if(p) { Push(S,p); p = p->lchild; }
else { Pop(S,q); cout << q->data; //Pop(S,q),將棧頂元素彈出,並使q指向該元素
p = q->rchild; }
} // while
return OK;
}
3.層次遍歷算法
對於一顆二叉樹,從根結點開始,按從上到下,從左到右的順序訪問每一個結點。(每個結點僅訪問一次)
算法設計思路:使用一個隊列
I. 將根結點進隊;
II.隊不空時循環:從隊列中出列一個結點*p,訪問它:
①若它有左孩子結點,將左孩子結點進隊
②若它有右孩子結點,將右孩子結點進隊
使用隊列類型定義如下:
typedef struct{
BTNode data[MaxSize]; //存放隊中元素
int front, rear; //隊頭和隊尾指針
}SqQueue; //順序循環隊列類型
二叉樹層次遍歷算法:
void LevelOrder(BTNode *b)
{
BTNode *p; SqQueue *qu;
InitQueue(qu); //初始化隊列
enQueue(qu,b); //根結點指針進入隊列
while(!QueueEmpty(qu)) //隊不爲空,則循環
{
deQueue(qu,p); //出隊結點p
cout << p->data;
if(p->lchild!=NULL) enQueue(qu,p->lchild);
//有左孩子時將其進隊
if(p->rchild!=NULL) enQueue(qu,p->rchild);
} //有右孩子時將其進隊
}
4.根據遍歷序列確定二叉樹
- 若二叉樹中各結點的值均不相同,則二叉樹結點的先序序列、中序序列和後序序列都是唯一的。
- 由二叉樹的先序序列和中序序列,或由二叉樹的後序序列和中序序列可以確定唯一一個二叉樹。