medium 剑指 Offer 二叉搜索树与双向链表 递归 栈 中序遍历

在这里插入图片描述
在这里插入图片描述


递归:

要求返回的“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 

在这里插入图片描述


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值