树/链表 -36.二叉搜索树与双向链表

在这里插入图片描述
在这里插入图片描述
思路:我们不难发现二叉搜索树的中序遍历实际上就是一个排序的序列。
中序遍历:左子树 ,根, 右子树

我们可以将节点的 left 指向比它小的的节点,right 指向 比它大的节点。

由于题目提供的节点类并没有指向父节点的引用,所以我们必须要保存好上一个比它小的节点,否则 left 就没有办法引用了。
所以我们将 pre 也就是比它小的节点引用定义为全局变量。

由于是一个双向链表,那么我们就要把最后一个访问的节点也要保存起来,最后用来指向头节点。我们把最后一个访问的节点定义为 tail。
所以我们也要将 tail 定义为全局变量去储存下来。

最后就是我们的head,链表的头指针,由于我们中序遍历到左子树的最左节点时(最小节点),我们需要把head指向它。但是树的递归中我们之后再也不会用到 head 引用,所以我们也可以把它定义为全局变量,再方法用只运用一次即可。

所以第一步,我们要中序遍历,当遍历到最左节点时,我们就需要把 head 指向 当前的节点。
第二步,中序遍历时,保存当前最后的访问节点,也就是tail,当遍历结束时我们就清楚哪一个节点是最大值。
第三步:中序遍历结束后,我们要把tail 指向 head 而 head.pre,要指向tail,
最后返回head即可。

    class Node {
        public int val;
        public Node left;
        public Node right;

        public Node() {}

        public Node(int _val) {
            val = _val;
        }

        public Node(int _val,Node _left,Node _right) {
            val = _val;
            left = _left;
            right = _right;
        }
    }
    private Node head = null;
    private Node pre = null;
    private Node tail = null;
    public Node treeToDoublyList(Node root) {
        if(root == null) return null;
        inorder(root);
        //当中序遍历链接过程结束,那么就将改变引用指向,形成真正的双向环形链表
        head.left = tail;
        head = tail.right;
        return head;
    }
    public void inorder(Node root){
        //当前节点
        Node current = root;
        //遍历左子树
        if(current.left != null)
            inorder(current.left);
        //当第一次左子树为空时,也就是pre为null时,我们将head指向最左节点
        if(pre == null) {
            head = current;
        }
        else{
            //证明此时的节点不是最左节点。那么就让前一个节点的right指向当前节点。
            pre.right = current;
            current.left = pre;
        }
        //当前的节点。
        //保存当前最后访问的一个节点
        tail = current;
        //进入到右子树时上一个节点就是pre,也就是当前的节点了。
        pre = current;

        //遍历右子树
        if(current.right != null)
            inorder(current.right);



    }



原创文章 139 获赞 23 访问量 5935

猜你喜欢

转载自blog.csdn.net/weixin_44916741/article/details/104304388