二叉樹的先序遍歷-遞迴和非遞迴演算法
阿新 • • 發佈:2018-11-17
需要實踐先序遍歷,我們先建立二叉樹。這裡採用先序序列建立二叉樹,不為別的,因為簡單。
typedef int ElemType; typedef struct BiTNode{ ElemType data; struct BiTNode *lchild, *rchild; }*BiTree, BiTNode; void CreateBiTreePreOrder(BiTree &T){ ElemType data; cin>>data; if(data==-1){ T=NULL; }else{ T = new BiTNode();//(BiTree)malloc(sizeof(BiTNode)); } if(!T){ return; }else{ T->data = data; CreateBiTreePreOrder(T->lchild); CreateBiTreePreOrder(T->rchild); } }
下面是對先序遍歷的實現:
① 首先是最簡單的先序遞迴演算法
遞迴的思想就是將需要重複的步驟分離出來,反覆呼叫,而且下一次的呼叫需要用到上一次呼叫的結果。(可以理解為有依賴關係存在)
//遞迴的先序遍歷
void PreOrder(BiTree T){
if(T){
cout<<T->data<<" ";
PreOrder(T->lchild);
PreOrder(T->rchild);//這裡的壓棧,只是為了再一次呼叫上面的函式
}
}
②下面來對遞迴演算法進行非遞迴實現
方法一:模擬遞迴演算法的操作過程。
按照先序的思想,可以轉化為迴圈控制。
- 入棧前,先輸出本節點資訊;
- 先左子樹一次入棧,直到沒有左子樹的結點為止;
- 出棧棧頂元素,然後,找到右子樹,繼續①②操作,直到棧為空 且 結點為空。
在遍歷的過程中,進棧、出棧可能會出現棧空的情況,但這時候遍歷還沒有結束, 故而採用雙重判斷。
//先序遍歷非遞迴演算法 void PreOrder(BiTree bt){ //需要用到棧,這裡簡單寫作一個數組來用, 最好用鏈棧,定義好入棧、出棧的操作介面 BiTree T = bt; BiTree ptr[20]; int top = -1; while(T || top!=-1){ //按照上面的遍歷,先輸出資料,然後左子樹入棧 while(T){ cout<<T->data<<" "; ptr[++top]=T; T=T->lchild; } if(top!=-1){ T = ptr[top--]; T = T->rchild; } } }
方法二:分析先序遍歷的特點。
充分考慮先序遍歷的特點
- 1入棧。
- 1出棧(棧頂元素出棧),輸出棧頂元素1,並將1的左右孩子節點入棧;其中右孩子4先入棧,然後左孩子2入棧。(因為,對左邊孩子的訪問先序遍歷先於右孩子,後入棧的先訪問)。
- 2出棧(棧頂元素出棧),輸出棧頂元素2,並將2的左右孩子節點入棧,同理5先入棧,3後入棧。
- 3出棧(棧頂元素出棧),輸出棧頂元素3,3為葉子結點,無孩子,本次無入棧。
- 5出棧(棧頂元素出棧),輸出棧頂元素5
- 4出棧(最後的棧頂元素出棧),此時 棧空,遍歷完畢。
void PreOrder(BiTree bt){
BiTree ptr[20];
int top = -1;
BiTree pt = bt;
ptr[++top] = pt;
while(top!=-1){
pt = ptr[top--];//每次棧頂元素出棧
cout<<pt->data<<" ";//輸出
if(pt->rchild)
ptr[++top] = pt->rchild;
if(pt->lchild)
ptr[++top] = pt->lchild;
}
}
-----------------------------------------分割線------------------------------------------------------------
測試截圖:
作者:無涯明月
發文時間:2018-11-16