作者:敲代码の流川枫

博客主页:​​流川枫的博客​​

专栏:​​和我一起学java​​

语录:Stay hungry stay foolish

工欲善其事必先利其器,给大家介绍一款超牛的斩获大厂offer利器——牛客网

​点击注册和我一起刷题​

 

二叉搜索树与双向链表_双向链表

文章目录

​​JZ36 二叉搜索树与双向链表​​

​​知识点1:二叉树递归​​

​​知识点2:二叉搜索树​​

​​思路​​

​​代码​​


JZ36 二叉搜索树与双向链表

OJ链接

​二叉树搜索树与双向链表​

描述

输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。如下图所示

 

二叉搜索树与双向链表_双向链表_02

数据范围:输入二叉树的节点数 0 \le n \le 10000≤n≤1000,二叉树中每个节点的值 0\le val \le 10000≤val≤1000
要求:空间复杂度O(1)O(1)(即在原树上操作),时间复杂度 O(n)O(n)

注意:

1.要求不能创建任何新的结点,只能调整树中结点指针的指向。当转化完成以后,树中节点的左指针需要指向前驱,树中节点的右指针需要指向后继
2.返回链表中的第一个节点的指针
3.函数返回的TreeNode,有左右指针,其实可以看成一个双向链表的数据结构

4.你不用输出双向链表,程序会根据你的返回值自动打印输出

 

二叉搜索树与双向链表_二叉搜索树_03

知识点1:二叉树递归

递归是一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解。因此递归过程,最重要的就是查看能不能讲原本的问题分解为更小的子问题,这是使用递归的关键。

而二叉树的递归,则是将某个节点的左子树、右子树看成一颗完整的树,那么对于子树的访问或者操作就是对于原树的访问或者操作的子问题,因此可以自我调用函数不断进入子树。

知识点2:二叉搜索树

二叉搜索树是一种特殊的二叉树,它的每个节点值大于它的左子节点,且大于全部左子树的节点值,小于它右子节点,且小于全部右子树的节点值。因此二叉搜索树一定程度上算是一种排序结构。

思路

二叉搜索树最左端的元素一定最小,最右端的元素一定最大,符合“左中右”的特性,因此二叉搜索树的中序遍历就是一个递增序列,我们只要对它中序遍历就可以组装称为递增双向链表。 

具体做法

定义两个指针pCur和prev, pCur的当前节点的指针, prev是pCur的前驱节点的指针, 因此只要pre不为空, 连接方案就是prev.right = pCur, pCur.left = prev

二叉树中序遍历的顺序是左儿子->根节点->右儿子, 故我们只要按中序遍历的顺序移动prev和pCur指针, 就可以将整个二叉树连接为一条双向链表

二叉搜索树与双向链表_二叉搜索树_04

 

代码

/**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;

public TreeNode(int val) {
this.val = val;

}

}
*/
public class Solution {
public TreeNode Convert(TreeNode pRootOfTree) {
if(pRootOfTree == null){
return null;
}
TreeNode head = pRootOfTree;
convertChild(pRootOfTree);
while(head.left!=null){
head = head.left;
}
return head;
}
TreeNode prev = null;
//pCur为当前节点
private void convertChild(TreeNode pCur){
//递归出口
if(pCur == null){
return ;
}
//中序遍历,先找到最左边的节点,并与prev建立连接
convertChild(pCur.left);
pCur.left = prev;
if(prev != null){
prev.right = pCur;
}
//prev更新
prev = pCur;
convertChild(pCur.right);
}
}