Morris神級遍歷二叉樹,時間複雜度為O(1)

2021-08-07 06:32:20 字數 2730 閱讀 6678

morris演算法介紹

morris演算法在遍歷的時候避免使用了棧結構,而是讓下層到上層有指標,具體是通過底層節點指向null的空閒指標返回上層的某個節點,從而完成下層到上層的移動。我們知道二叉樹有很多空閒的指標,比如某個人節點沒有右孩子,我們稱這種情況為空閒狀態,morris演算法的遍歷就是利用了這些 空閒的指標!

morris演算法演算法的規則:

當我拿到乙個節點(node)的時候看它有沒有左子樹,沒有的話向右指標方向移動

有的話找到左子樹的最右節點,如果這個最右節點的右指標為空則讓它指向node,然後node向左指標移動

,如果這個最右節點已經指向node,則讓它指向空則讓node向右指標移動

我們就拿乙個普通的二叉樹來說吧:

描述:我們從根節點開始,node節點就為1,1有左子樹,找到1左子樹的最右節點為5,5的右指標為空,讓5的右指標指向node即1,然後node向左指標移動,變為2,2也有左子樹,左子樹的最右節點為4,4的右指標為空則指向2,node向左移動變為4,node為4沒有左子樹,所以node向右指標方向移動回到2(這是第二次來到2),2有左子樹,並且它左子樹的最右節點已經指向了node(即2),則讓這個最右節點指向null,node向右指標移動來到5,5沒有左子樹,向右指標移動來到1,1有左子樹,切左子樹的最右節點指向了node(即自己),讓最右節點指向null,node向右指標移動來到3,3有子樹,左子樹的最右節點右指標為空所以讓他指向node(即3),node向左指標移動來到7,7沒有左子樹,向右指標移動回到3(第二次來到3),3有左子樹切左子樹的最右節點指向自己,則讓左子樹的最右節點指向null,node往右指標走,來到8,此樹遍歷完畢。

我們可以看到節點2,1,3在node走的過程中會兩次來到它,而其他節點node只會來到一次!

歸納為:如果乙個節點有左子樹node就會訪問它兩次,如果沒有左子樹,node只會訪問它一次。

這樣我們就可以開始做前、中序遍歷了:

前序遍歷:

乙個節點沒有左子樹直接列印當前節點

如果有的話(第一次來到此節點的時候就去列印),即再往左子樹節點走之前列印

code

struct node

};//morris前序遍歷

void morrispre(node* root)

if(cur2->right ==

null)

else

}else

cur1 = cur->right;

}cout<

}

中序遍歷在沒有左子樹的時候直接往右子樹走之前列印

有左子樹先去遍歷左子樹然後回來當前節點列印,之後再去右子樹(都是往右指標走之前列印他)

code

//morris中序遍歷

void morrisin(node* root)

if(cur2->right ==

null)

else

}cout

" ";

cur1 = cur1->right;

}cout<

}

後序遍歷後序遍歷就有點麻煩了,我們仔細觀察前面的前中序,node最多可以訪問乙個節點兩次,前序是第一次訪問就列印當前節點,中序是第二次訪問列印當前節點,那麼後序需要第三次訪問的時候列印當前節點,但是乙個節點最多被訪問兩次,那怎麼辦呢?

下來我們引入乙個方法:

圖中紅線畫出來的稱為這棵二叉樹的所有右邊界,所有的右邊界節點加起來就是二叉樹的節點個數n,每個節點最多可能被遍歷2次,遍歷整體二叉樹的代價就是2n

後序的方法就是:

第二次來到到此節點,逆序列印它的右邊界就是後序,整個走完之後(遍歷到二叉樹最右節點)後單獨逆序列印整棵樹的右邊界。

那怎麼逆序列印呢?類似於單鏈表的逆置,更改右節點的指標指向即可,在列印完在更改回去,(如1->right = 3,3->right = 8,可以設定為 8->prev = 3,3->pre = 1)

code

/morris後序遍歷

void printedge(node* from);

void morrispos(node* root)

node* cur1 = root;

node* cur2 =

null;

while(cur1 !=

null)

if(cur2->right ==

null)

else

}cur1 = cur1->right;

}printedge(root);

cout<

}void reverseedge(node* from);

void printedge(node* root)

reverseedge(tail);

}node reverseedge(node* from)

return pre;

}

Morris神級遍歷二叉樹

morris遍歷是二叉樹遍歷演算法的超強高階演算法,跟遞迴 非遞迴 棧實現 的空間複雜度,morris遍歷可以將非遞迴遍歷中的空間複雜度降為o 1 從而實現時間複雜度為o n 而空間複雜度為o 1 的精妙演算法。morris遍歷利用的是樹的葉節點左右孩子為空 樹的大量空閒指標 實現空間開銷的極限縮減...

Morris遍歷二叉樹

morris遍歷的實質就是避免用棧結構,而是讓下層到上層有指標,具體是通過讓底層節點指向null的空閒指標指回上層的某個節點,從而完成下層到上層的移動。中序遍歷的過程如下 1.假設當前子樹的頭節點為h,讓h的左子樹中最右節點的right指標指向h,然後h的左子樹繼續步驟1的處理過程,直到遇到某乙個節...

Morris遍歷(二叉樹)

對於每乙個節點來說 對於上面這副圖來說,整個過程 進入節點5 構建 4 5右連線 進入節點3 構建 1 3右連線 進入節點1 列印1 通過 1 3 連線進入3 進入節點3 第二次進入3,列印3 進入節點4 列印4 通過 4 5 連線進入5 進入節點5 第二次進入5,列印5 注意 中序遍歷利用右子節點...