二叉樹遍歷 遞迴 非遞迴實現

2021-09-24 20:43:15 字數 2207 閱讀 3057

先序遍歷中序遍歷

後序遍歷

根結點-左子樹-右子樹

左子樹-根子樹-右子樹

左子樹-右子樹-根結點

//先序遍歷

void

preorder

(btree t)

}//中序遍歷

void

inorder

(btree t)

}//後序遍歷

void

postorder

(btree t)

}

遞迴(recursion)就是子程式(或函式)直接呼叫自己或通過一系列呼叫語句間接呼叫自己。該執行過程要求每一次節點中斷呼叫其他方法,必須記錄下該中斷節點的環境資訊,作用是為了呼叫結束返回結果之後原程式能夠從上次中斷位置起繼續執行,在計算機中,通過乙個結構來實現該效果(棧:先進後出):

但遞迴演算法的執行效率較低,這是因為遞迴需要反覆入棧,時間和空間的開銷都比較大。

(從本質上來看,遞迴其實是方便了程式設計師卻難為了機器)

為了避免這種開銷,需要消除遞迴,方法主要有兩種:

1.針對簡單遞迴,利用迭代代替遞迴;

2.利用棧的方式實現:利用人工棧模擬系統堆疊。(這種方法通用性強,但是本質上還是遞迴的,區別是將計算機做的事情改由人工來完成)

利用棧實現的非遞迴過程可分為如下步驟

設定乙個工作棧,用於儲存遞迴工作記錄,包括實參、返回位址等;

將呼叫函式傳遞而來的引數和返回位址入棧;

演算法思想:

從二叉樹的根結點開始,將根結點設為當前結點p,執行以下操作:

邊遍歷邊列印,並存入棧中(一開始當前結點p為根結點)→先列印當前結點p的資料→再將當前結點p入棧→若左孩子存在,將左孩子設為當前結點→重複執行此操作,直至到達二叉樹左子樹最左下角;

棧頂元素出棧,將棧頂元素設為當前結點p→若當前結點p的右孩子存在,將右孩子設為當前結點p(進入右子樹)→回到步驟1,重複執行 1、2,直至棧空。

void

preorder

(btree t)

while

(p!=

null

||top>0)

//當p為空時,說明根和左子樹都遍歷完了,該進入右子樹了

if(top>0)

/* //另一種寫法

if(p!=null)else

*/}}

演算法思想

從二叉樹的根結點開始,將根結點設為當前結點p,執行以下操作:

當前結點p入棧(一開始當前結點p為根結點)→若當前結點p存在左孩子→將左孩子設為當前結點p→重複此操作,直至到達二叉樹左子樹最左下角;

將棧頂元素出棧,將出棧元素設為當前結點p→列印該結點p的資料;

若當前結點p存在右孩子,則將右孩子設為當前 結點p→回到步驟1,重複執行 1、2、3,直至棧空。

void

inorder

(btree t)

while

(p!=

null

||top>0)

//出棧

if(top>0)

/* if(p!=null)else

*/}}

演算法思想

當前結點入棧(一開始當前結點為根結點)→若當前結點存在左孩子→將左孩子設為當前結點→重複此操作,直至到達二叉樹左子樹最左下角;

取棧頂元素,並設為當前結點pcur:

void

postorder

(btree t)

while

(pcur!=

null

||top>0)

if(top>0)

else}/*

if(pcur!=null)elseelse}*/

}}

二叉樹遍歷(遞迴 非遞迴)

二叉樹以及對二叉樹的三種遍歷 先根,中根,後根 的遞迴遍歷演算法實現,以及先根遍歷的非遞迴實現。node public class node public node left public node right public object value 遍歷訪問操作介面 public inte ce ...

二叉樹遞迴 非遞迴遍歷(Java實現)

遍歷是對一顆二叉樹最基本的操作,有前序遍歷 中序遍歷 後序遍歷和層次遍歷四種,都可以通過遞迴或者資料結構實現。假定葉子結構如下 static classleaf publicstring tostring 1.前序遍歷 先訪問其根節點,再訪問其左節點,最後訪問其右節點。遞迴實現 先訪問其根節點,然後...

二叉樹遍歷遞迴和非遞迴實現

遍歷一共有三種,前序中序後序,下面直接上 吧,外加執行結果 include include include include include using namespace std 定義乙個樹節點 typedef struct tag tree node tree node,tree node p 建...