递归:
要求返回的“head” 表示指向链表中有最小元素的节点,即中序遍历的第一个。需要先找到树最左节点,二叉查找树的中序遍历序列一定是从小到大排列的。
中序遍历:左中右
c++
为对二叉树作 “左、根、右” 顺序遍历,递归实现如下:
void dfs(Node* root) {
if(root == nullptr){
return;
}
dfs(root->left); // 左
cout << root->val << endl; // 根
dfs(root->right); // 右
}
class Solution {
public:
Node* treeToDoublyList(Node* root) {
if(root == nullptr){
return nullptr;
}
dfs(root);
// 连接头尾
head->left = pre;
pre->right = head;
return head;
}
private:
Node *pre = nullptr;
Node *head = nullptr;
void dfs(Node* cur){
if(cur == nullptr){
return; // 递归出口,cur移到尾指针的right(nullptr),return void
}
// 递归循环
// 要求返回的“head” 表示指向链表中有最小元素的节点,即中序遍历的第一个
dfs(cur->left); // 中序遍历,先处理左节点(cur->left)
// 中序遍历,再处理根节点(cur)
if(pre != nullptr){
pre->right = cur;
}else{
head = cur; // cur为整棵树最左节点
}
cur->left = pre;
pre = cur; // pre指针右移
dfs(cur->right); // 中序遍历,最后处理右节点(cur->right)
}
};
python
class Solution:
def treeToDoublyList(self, root: 'Node') -> 'Node':
def dfs(cur):
if not cur:
return
dfs(cur.left) # dfs中调用dfs不用self.dfs
if self.pre: #
self.pre.right = cur
cur.left = self.pre
else:
self.head = cur # 保留头节点
self.pre = cur # pre指针右移
dfs(cur.right)
if not root:
return
self.pre = None
self.head = None
dfs(root)
self.head.left = self.pre
self.pre.right = self.head
return self.head
栈:
c++
class Solution {
public:
Node* treeToDoublyList(Node* root) {
if(root == nullptr){
return nullptr;
}
Node* pre = root;
Node* cur = nullptr;
stack<Node*> stk; // 栈 放遍历到的左节点
while(pre != nullptr){
stk.push(pre);
pre = pre->left;
}
Node* head = stk.top(); // 保存头节点
while(!stk.empty()){
cur = stk.top();
if(pre != nullptr){
pre->right = cur;
cur->left = pre;
}
pre = cur;
cur = cur->right; // 中->右
stk.pop();
while(cur != nullptr){
stk.push(cur); // '右'节点入栈
cur = cur->left; // 遍历'右'树
}
}
// 衔接首尾结点形成循环链表
head->left = pre;
pre->right = head;
return head;
}
};
python
class Solution:
def treeToDoublyList(self, root: 'Node') -> 'Node':
if not root:
return
pre = root
head = None
stk = []
while pre:
stk.append(pre)
pre = pre.left # pre为最左节点的左节点 nullptr
head = stk[-1] # stk[-1]为最左节点(非空) # 保留头节点
while stk:
cur = stk.pop() # stk[-1]为最左节点(非空)
if pre:
pre.right = cur
cur.left = pre
pre = cur # pre指针右移
cur = cur.right # cur指针右移 中->右
右
while cur:
stk.append(cur) # '右'节点入栈
cur = cur.left # 遍历'右'树
# 衔接首尾结点形成循环链表
head.left = pre
pre.right = head
return head