欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

牛客——二叉搜索树与双向链表

程序员文章站 2022-05-06 21:42:11
...

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

题目分析
这道题怎么说呢,牛客标它的难度是最低的这我是不太认同的。首先从题目描述来看,不读个3、4遍可能不知道它是什么意思,同时又考察了链表和二叉树这两种结构。嗯不知道牛客难度标记是不是越小越不好做,很魔性。

正题:
先来看一棵简单的二叉搜索树
牛客——二叉搜索树与双向链表
由他变成一个有序的双向链表还是比较简单的。如下图:
牛客——二叉搜索树与双向链表
接下来升级二叉搜索树的复杂程度
牛客——二叉搜索树与双向链表
他怎么变呢?先变简单的把它的子树先转成链表
牛客——二叉搜索树与双向链表
接下来改变根节点的指针指向,把它链到3、5中间
牛客——二叉搜索树与双向链表
到这里我们基本上可以这道题要采用什么方法了,还是树的常用操作——递归。但是每次做些什么?
一个节点和三个节点组成的子树操作是相同的,只需把此子树的左右子节点回链子树根节点即可。
接下来就要考虑向上图这样更高一层的树了。
子树成链表就不用说了,重点是怎么把根节点链到中间去。首先上面根节点开始指针指的是2和6,我们要做的操作是修改指向,让它指3和5.故涉及到链表找节点的问题(这在链表操作很常见,看操作即可)指向完了,回链即可。

代码实现:

/* function TreeNode(x) {
    this.val = x;
    this.left = null;
    this.right = null;
} */
function Convert(pRootOfTree)
{
    // write code here
    if(pRootOfTree==null){
        return null;
    }
     //找左子树最右
    function find_right(node){
        while(node.right){
            node=node.right;
        }
        return node;
    }
    //拿左子树链表
    let leftNode = Convert(pRootOfTree.left);
    //拿右子树右子树
    let rightNode = Convert(pRootOfTree.right);
    //链表头节点
    let  retNode = leftNode;
    if(leftNode){
        //若左子树链表存在,则找其最右
         leftNode = find_right(leftNode);
    }else{
        //不存在左子树则根节点就作为链表头节点
        retNode = pRootOfTree;
    }
    
      //pRootOfTree的左子结点链上leftNode
        pRootOfTree.left = leftNode;
        //pRootOfTree的右子结点链上右子结点
        pRootOfTree.right = rightNode;
        //回链
        if(leftNode){
             leftNode.right = pRootOfTree;
        }
        if(rightNode){
           rightNode.left = pRootOfTree;
        }
        //返链表头节点
        return retNode;
    
    
}

牛客——二叉搜索树与双向链表