二叉搜尋樹與雙向連結串列(Python and C++版本)
阿新 • • 發佈:2020-07-11
題目:
輸入一棵二叉搜尋樹,將該二叉搜尋樹轉換成一個排序的迴圈雙向連結串列。
要求不能建立任何新的節點,只能調整樹中節點指標的指向。我們希望將這個二叉搜尋樹轉化為雙向迴圈連結串列。連結串列中的每個節點都有一個前驅和後繼指標。對於雙向迴圈連結串列,第一個節點的前驅是最後一個節點,最後一個節點的後繼是第一個節點。“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 = val4 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 ifself.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 };