1. 程式人生 > 實用技巧 >二叉搜尋樹與雙向連結串列(Python and C++版本)

二叉搜尋樹與雙向連結串列(Python and C++版本)

題目:

輸入一棵二叉搜尋樹,將該二叉搜尋樹轉換成一個排序的迴圈雙向連結串列。

要求不能建立任何新的節點,只能調整樹中節點指標的指向。我們希望將這個二叉搜尋樹轉化為雙向迴圈連結串列。連結串列中的每個節點都有一個前驅和後繼指標。對於雙向迴圈連結串列,第一個節點的前驅是最後一個節點,最後一個節點的後繼是第一個節點。“head” 表示指向連結串列中有最小元素的節點。

特別地,我們希望可以就地完成轉換操作。當轉化完成以後,樹中節點的左指標需要指向前驅,樹中節點的右指標需要指向後繼。還需要返回連結串列中的第一個節點的指標。

來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/er-cha-sou-suo-shu-yu-shuang-xiang-lian-biao-lcof

思路:

  二叉搜尋樹的中序遍歷是遞增序列,所以符合轉換為排序連結串列的要求。

  在構建相鄰節點時,由於是雙向連結串列(當前節點cur,前繼節點pre),所以不僅要求pre.right = cur,還要求cur.left = pre。

  由於連結串列還是迴圈連結串列,因此需要連線首尾節點(head,tail),得到head.left = tail, tail.right = head。

Python版本:

 1 class Node:
 2     def __init__(self, val, left=None, right=None):
 3         self.val = val
4 self.left = left 5 self.right = right 6 7 class Solution: 8 def treeToDoublyList(self, root: 'Node') -> 'Node': 9 def dfs(cur): 10 if not cur: # 如果當前節點為空,說明已經越過葉節點,遞迴終止 11 return 12 13 dfs(cur.left) # 遞迴左子樹 14 15 if
self.pre: # 當前節點不是頭結點,可以修改指標指向 16 self.pre.right = cur 17 cur.left = self.pre 18 else: # pre為空,說明當前是頭節點,記錄為head 19 self.head = cur 20 self.pre = cur # 將pre更新為cur 21 22 dfs(cur.right) # 遞迴右子樹 23 if not root: return None 24 self.pre = None # pre位於cur左側,初始化為None 25 dfs(root) 26 self.head.left = self.pre # 全部迭代完成後,pre指向雙向連結串列中的尾節點 27 self.pre.right = self.head 28 return self.head

C++版本:

 1 class Node {
 2 public:
 3     int val;
 4     Node* left;
 5     Node* right;
 6 
 7     Node() {}
 8 
 9     Node(int _val) {
10         val = _val;
11         left = NULL;
12         right = NULL;
13     }
14 
15     Node(int _val, Node* _left, Node* _right) {
16         val = _val;
17         left = _left;
18         right = _right;
19     }
20 };
21 
22 class Solution {
23 public:
24     Node *pre;  // 宣告前繼節點
25     Node *head;  // 連結串列宣告頭結點
26     Node* treeToDoublyList(Node* root) {
27         if (root == NULL)    return NULL;
28         pre = NULL;  // pre位於連結串列頭結點左側,所以初始化前繼節點為空
29         dfs(root);
30         head->left = pre;  // 遞迴完成時,pre指向的是尾結點
31         pre->right = head;
32         return head;
33     }
34 
35     void dfs(Node* cur) {
36         if (cur == NULL)
37             return;  // 遞迴終止條件
38 
39         dfs(cur->left);  // 遞迴左子樹
40 
41         if (pre) {  // pr非空說明cur不是頭結點
42             pre->right = cur;
43             cur->left = pre;
44         }
45         else
46             head = cur;  // 當前節點是頭結點,記錄為head
47         pre = cur;  // pre更新為cur
48 
49         dfs(cur->right);  // 遞迴右子樹
50     }
51 };