输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。
这道题让我们按照中序遍历的顺序链接树的节点形成循环链表。最简单的方法莫过于用vector或者queue记录访问顺序,然后得到序列挨个链接即可。
当然我们这里希望时间效率更高就得一边遍历一边连接好。难点在于如何在遍历的过程中处理前后指针。
那么最直接的想法就是用一个Pre指针记录前一个遍历的节点,然后每次对于当前节点,链接和pre的双向箭头。
中序遍历:
dfs(left)——root处理——dfs(right), 用pre表示前一个节点,每次root处理后即让pre = root。
特别注意:这里的指针是指针的引用,因为我们在递归中篡改它的值,如果搞不清引用就全局变量,这里debug半天的错误就是因为没加引用!!
void inorder(Node* root,Node*& pre, Node*& head){
if(head==nullptr && root->left==nullptr)
head = root;
if(root->left)
inorder(root->left,pre,head);
if(pre!=nullptr){
pre->right = root;
root->left = pre;
}
pre = root; // 表示当前visit root结束
if(root->right)
inorder(root->right,pre,head);
return;
}
Node* treeToDoublyList(Node* root) {
if(root==nullptr)
return nullptr;
Node* head=nullptr,*endNode=root;
Node* pre=nullptr;
inorder(root,pre,head);
pre->right = head;
head->left = pre;
return head;
}
更新写法2:
class Solution {
public:
Node*pre=nullptr, *leftmost=nullptr;
void inorder(Node* root){
if(root==nullptr){
return;
}
inorder(root->left);
if(pre == nullptr)
leftmost = root;
else
pre->right = root;
root->left = pre;
pre = root;
inorder(root->right);
}
Node* treeToDoublyList(Node* root) {
inorder(root);
Node* rightmost = pre;
if(leftmost && rightmost){
leftmost->left= rightmost;
rightmost->right = leftmost;
}
return leftmost;
}
};