剑指offer-二叉搜索树与双向链表

本文介绍两种方法将二叉搜索树转换为排序的双向链表:一是递归法,通过找到左子树的最右节点和右子树的最左节点,与根节点建立连接;二是借助数组法,利用二叉搜索树的中序遍历特性,先存储节点顺序,再进行双向链接。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。
要求不能创建任何新的结点,只能调整树中结点指针的指向。

方法一: 使用递归

第一种方法是用递归去操作. 每一次递归的核心思想:

找到左子树的最右节点, 和右子树的最左节点, 与根节点进行连接.

然后对左子树和右子树做相同操作即可.

    public TreeNode convertRecursive(TreeNode pRootOfTree) {
        if (pRootOfTree == null) return null;
        if (pRootOfTree.left == null && pRootOfTree.right == null) return pRootOfTree;
        TreeNode left = convertRecursive(pRootOfTree.left);
        TreeNode curNode = left;
        // 找到左子树最右节点
        while (curNode != null && curNode.right != null) {
            curNode = curNode.right;
        }
        if (left != null) {
            pRootOfTree.left = curNode;
            curNode.right = pRootOfTree;
        }
        TreeNode right = convertRecursive(pRootOfTree.right);
        curNode = right;
        // 找到右子树最左节点
        while (curNode != null && curNode.left != null) {
            curNode = curNode.left;
        }
        if (right != null) {
            pRootOfTree.right = curNode;
            curNode.left = pRootOfTree;
        }
        // 判断左子树为空的情况
        return left == null ? pRootOfTree : left;
    }

方法二: 借助数组

二叉搜索树的中序遍历序列就是二叉树的递增序列.

根据这一思想, 我们可以先把BST的按递增顺序的节点(中序遍历序列)用顺序表存起来.

之后直接按顺序进行双向连接即可.

返回值使用list.get(0)即可.(对应最小节点)

    /*
    思路: 使用ArrayList, 将中序遍历序列存储起来, 再依次进行连接即可.
    */
    public TreeNode convertByArrayList(TreeNode root) {
        if (root == null) return null;
        // 获得中序遍历序列
        ArrayList<TreeNode> list = new ArrayList<>();
        Stack<TreeNode> stack = new Stack<>();
        TreeNode cur = root;
        while (cur != null || !stack.isEmpty()) {
            // 压入左子树
            while (cur != null) {
                stack.push(cur);
                cur = cur.left;
            }
            cur = stack.pop();
            list.add(cur);
            cur = cur.right;
        }
        
        for (int i = 0; i < list.size() - 1; i++) {
            if (list.get(i) == null) continue;
            list.get(i).right = list.get(i+1);
            list.get(i+1).left = list.get(i);
        }
        
        return list.get(0);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值