二叉樹遍歷小結

2021-10-13 05:19:48 字數 4252 閱讀 3898

二叉樹是相當重要的資料結構,目前我還只會玩玩它的遍歷(年輕不懂事沒好好學,不然早就達到人生巔峰了),leetcode上二叉樹的簡單題,大部分通過遍歷加一點小邏輯即可解決,所以總結一下幾種遍歷方法(其實也是看題解白嫖的)。

二叉樹遍歷有廣度優先,深度優先兩種方式,深度優先又分先序遍歷(根,左,右),中序遍歷(左,根,右),後序遍歷(左,右,根),如果是二叉搜尋樹,中序遍歷就是有序的了。廣度優先方式沒太多說,只能借助佇列實現,而深度優先,可通過遞迴方式,借助棧迭代方式,還有一種巧妙的莫里斯演算法,空間複雜度是o(1),但莫里斯演算法應該會改變樹的結構。

首先將根結點入隊,然後只要佇列非空,就出隊乙個元素,然後只要子節點不為空就入隊,隊列為空時,就是遍歷完成時

public

intbfs

(treenode root)

int depth=0;

while

(!queue.

isempty()

)if(null!=curnode.right)}}

return depth;

}

遞迴方式**很簡潔,調整一下順序前中後序遍歷也都出來了。然後不斷地巢狀函式呼叫,不管哪種語言每次函式呼叫作業系統都需要壓棧,jvm中每次方法呼叫也是需要建立棧幀,如果資料量大會消耗大量記憶體,肯定會丟擲stackoverflowerror

1.先序

public

void

dfs(treenode root)

system.out.

println

(root.val)

;dfs

(root.left)

;dfs

(root.right);}

2.中序

public

void

dfs(treenode root)

dfs(root.left)

; system.out.

println

(root.val)

;dfs

(root.right);}

根右左遍歷

public

void

dfs(treenode root)

dfs(root.right)

; system.out.

println

(root.val)

;dfs

(root.left);}

3.後序

public

void

dfs(treenode root)

dfs(root.left)

;dfs

(root.right)

; system.out.

println

(root.val)

;}

深度優先先序迭代遍歷,先將根節點入棧,然後只要棧非空,就出棧乙個元素,這時需要將右子節點先入棧,左子節點**棧,這樣下一次迴圈出棧的是左子節點,再繼續下去就達到了目的

public list

dfs(treenode root)

stack

stack =

newstack

<

>()

; stack.

push

(root)

;//入棧根結點

while

(!stack.

isempty()

)if(null!=curnode.left)

}return res;

}

深度優先中序迭代遍歷,每次迴圈需要將根節點的所有左結點全部入棧,然後出棧最後乙個左子結點,即第乙個結點,如果該結點有右子結點,將根節點賦值為該右子結點,接著下一次迴圈,這樣又會把右子樹入棧,遍歷完後會回到第一次迴圈的父節點,棧為空後達到目的

public list

dfs(treenode root)

stack

stack =

newstack

<

>()

;while

(!stack.

isempty()

||null!=root)

treenode curnode=stack.

pop();

//彈出最後乙個左子結點

res.

add(curnode.val);if

(null!=curnode.right)

}return res;

}

深度優先後序迭代遍歷,每次迴圈需要將根節點的所有左結點全部入棧,然後出棧最後乙個左子結點,如果存在右孩子,入棧當前節點,指標移到右孩子,進入下一輪迴圈,一樣全部入棧左子結點,當右子結點為空,加入遍歷結果集,這是將指標值為空並將前驅結點置為此節點(前驅結點就是用於處理有右孩子的結點),下一輪迴圈,如果結點的右孩子等於前驅結點,也可以加入結果,一直迴圈到棧為空指標為空,遍歷完成

public list

dfs(treenode root)

stack

stack =

newstack

<

>()

; treenode pre=null;

//前驅結點

treenode curnode=root;

while

(!stack.

isempty()

||null!=curnode)

curnode=stack.

pop();

//出棧最後結點

if(null==curnode.right||curnode.right==pre)

else

}return res;

}

莫里斯演算法用巧妙的方式,將迭代遍歷的空間複雜度降低為o(1),**看起來沒有多太多,但是理解卻是需要更多的腦容量,這裡借用了的**,有助於理解。

1 如果當前結點沒有左子樹,輸出結點,當前結點指向右子結點,遍歷右子樹

2 如果當前結點有左子樹,找到該左字樹的最右子結點,如果最右子結點的右孩子為空,代表為根節點,輸出結點值,如果最右子結點的右孩子不為空,當前移動到右孩子

3 當前結點為空,結束迴圈

}1 如果當前結點沒有左子樹,輸出結點,當前結點指向右子結點,遍歷右子樹

2 如果當前結點有左子樹,找到該左字樹的最右子結點,如果最右子結點不為空,代表為最左結點,輸出結點值,然後回到父節點,或者右子結點

3 當前結點為空,結束迴圈

;//後全部加入遍歷集合

cur=cur.right;}}

}return res;

}

二叉樹的遍歷小結

二叉樹的非遞迴方式有不同的寫法,今小結了前序 中序 後序三種遍歷方式,分別用一到兩種非遞迴方式寫出來,還是那句話,要重點理解其思想,還有會快速的實現出來 include include include using namespace std 二叉樹相關 struct node 從陣列建樹 輸入 陣列...

構建二叉樹 遍歷二叉樹

陣列法構建二叉樹 public class main public static void main string args 用陣列的方式構建二叉樹 public static void createbintree 把linkedlist集合轉成二叉樹的形式 for int j 0 j 最後乙個父節...

二叉樹遍歷

二叉樹的遍歷非常重要,但對已一棵比較複雜的樹,要寫出它的先 中 後序遍歷,往往不是那麼簡單,也很容易犯錯。這裡介紹一種比較直觀且不容易犯錯的方法。對於圖1所示的二叉樹,要寫出它的先 中 後序遍歷,往往很容易出錯。圖 1 其實,我們可以用圖2中的紅線描畫出二叉樹的輪廓。圖 2 而對於樹上的每乙個節點,...