二叉搜尋樹轉化為雙向鍊錶

2021-09-13 12:21:06 字數 2568 閱讀 3220

首先需要明白二叉搜尋樹也是一種排序的資料結構,它的中序遍歷就是乙個不遞減的順序排列

所以如果要轉換成乙個排序好的雙向鍊錶,那麼僅需要改變原來指向左子節點和右子節點的指標,讓他們分別指向前節點和後節點即可,如圖所示

調整指標

原先指向左子節點的指標調整為鍊錶中指向前乙個節點的指標

原先指向右子節點的指標調整為鍊錶中指向後乙個節點的指標

如何調整

考慮根節點和左右子樹的根本情況,因為如果用遞迴,這種根本情況考慮就可以去將同樣的方法用到左右子樹上

對於這種基本情況,可以分成三個部分來看,根節點10,左子樹,右子樹,需要做的就是將10與左子樹中的最大值連起來,然後把10與右子樹中的最小值連起來

現在有個問題就是我們並不知道左子樹中的最大值和右子樹中的最小值,如果我們知道就好了。但是想到遞迴,遞迴到左子樹中,如果左子樹已轉換為雙向鍊錶,那麼雙向鍊錶的最後乙個節點就是我們想要的,而右子樹中的第乙個節點也是我們想要的

轉換**

public static binarytreenode baseconvert(binarytreenode root, binarytreenode lastnode) {

if (root == null)

return lastnode;

binarytreenode current = root;

if (current.leftnode != null)

lastnode=baseconvert(current.leftnode, lastnode);

current.leftnode = lastnode;

if (lastnode != null)

lastnode.rightnode = current;

lastnode = current;

if (current.rightnode != null)

lastnode=baseconvert(current.rightnode, lastnode);

return lastnode;

至於為什麼需要乙個lastnode,

上面的**中有兩個引數,乙個是根節點,乙個是已經轉換好的鍊錶的最後乙個節點,因為二叉搜尋樹中序遍歷的特性,當遍歷到根節點的時候,左子樹已經排好序了,所以會有乙個左子樹已經轉換好的鍊錶,而這個鍊錶的最後乙個節點即是我們需要和根節點左連的節點

至於為什麼需要乙個lastnode,假設當前節點的左子樹都排好序,那麼現在lastnode應該是左子樹的最大節點(也就是左子樹的右兒子的右兒子的右兒子直到沒有右兒子的那個節點。)如果不儲存lastnode找到當前節點的左子樹的最大節點是不容易的。

另外需要說明的是lastnode指向的是已經排好序的雙向鍊錶的尾節點(這個尾節點的pre已經指向完畢了,右節點還沒處理好。)

最開始的時候lastnode為null

current為當前子樹的根節點

如果左子樹存在,那麼轉換左子樹,遞迴下去,遞迴返回之後,說明找到了鍊錶的第乙個節點,也就是4那個節點,將4的前面節點置為null,此時current為4那個節點,這個時候由於6的4這個左子樹已遍歷完了,所以需要往上層返回,返回之前需要將current賦值給lastnode,說明4這個左子樹的最後乙個節點就是4

由於往上返回了一層,此時的current已經是6了,將6的左節點賦值為之前返回的4,判斷之前返回的lastnode是否為null,不為空說明需要把根節點和lastnode連起來,其實lastnode為null的情況就只有第乙個節點會出現,其他的時候都不會出現。現在已排好序的包括6的左子樹以及6本身了,所以此時的lastnode為6

6和4的雙向連線就完成了,由於6的右子樹存在,又會遞迴到右邊子樹去,由於8不存在左右子樹,遞迴下去一層之後current就是8這個節點,但它的左孩子為空,所以不會左邊遞迴下去,將8的左連線與之前的lastnode連線起來,建立雙向連線的一條連線,然後由於lastnode不為空,所以又把lastnode的右連線與8連線起來,至此雙向連線建立,此時lastnode為8

所以468都已排好序,此時lastnode為8,返回到上一層,也就是根節點10了,在這一層current為10,將current的左連線與lastnode連線起來,如果lastnode存在,將lastnode的右連線與10連線一起,以此建立雙向連線。至此就將根節點和左子樹都連線起來了,然後就是去轉換右子樹,現在的lastnode為10,current為14,14有左孩子,所以需要遞迴到下一層,下一層的current為12,12沒有左孩子,所以不用在坐遞迴,所以12是12這棵子樹轉換成雙向鍊錶的最左邊的節點,將lastnode與12連線,也就是10與12連線,此時的lastnode就變成了12,再將12的右子樹遞迴,由於沒有右子樹,所以直接返回到上一層,上一層的current是14,14與已排好序的lastnode連線,也就是12與14連線,然後lastnode變為14,遞迴到14的右子樹,也就current變為16,16再遞迴左子樹,無左子樹,將16與14連線,此時的lastnode變為16,遞迴右子樹,無右子樹,所以整個遞迴工作完成

二叉搜尋樹轉化為雙向鍊錶

整個過程可以看做是三部分的鍊錶化,左子樹 根節點和右子樹。遞迴地對這三部分進行鍊錶化,在鍊錶化中處理好左子樹最右節點與根節點的鏈結關係 根節點與右子樹的關係,那麼整個過程就能夠完成。treenode convert treenode root void convertnode treenode no...

將二叉搜尋樹轉化為雙向鍊錶

輸入一棵二叉搜尋樹,將該二叉搜尋樹轉換成乙個排序的雙向鍊錶。要求不能建立任何新的結點,只能調整樹中結點指標的指向。建立的雙向鍊錶的順序就是二叉搜尋樹的中序遍歷結果。這裡有遞迴和非遞迴解法。一般的非遞迴解法需要開闢額外的空間,本次借助morris演算法,給出一種不需要額外空間開銷的非遞迴解法。首先是遞...

二叉搜尋樹轉化為雙向鍊錶 js版本

leetcode原題 劍指 offer 36 輸入一棵二叉搜尋樹,將該二叉搜尋樹轉換成乙個排序的迴圈雙向鍊錶。要求不能建立任何新的節點,只能調整樹中節點指標的指向。我們希望將這個二叉搜尋樹轉化為雙向迴圈鍊錶。鍊錶中的每個節點都有乙個前驅和後繼指標。對於雙向迴圈鍊錶,第乙個節點的前驅是最後乙個節點,最...