26.二叉搜索树与双向链表
题目描述
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
解题思路
-
因为要对二叉搜索树重新排序为双向链表,因此可以看出此题应当用中序遍历,看到树的题目,基本要想到递归和前中后序遍历。
-
两种解题思路,均基于递归。
-
这里要注意:C++的指针类解法不能直接用于js,因为js的非基本数据类型的传递问题~ 可能会出错~
Code
- 解法一: 基础的递归
- 构建左子树为双向链表,返回链表头节点left
- 定位到左双向链表最后一个节点
- 左双向链表最后一个节点与当前节点双向链接
- 构建右子树为双向链表,返回链表头结点right
- 将右双向链表头节点和当前节点连接起来
- 返回双向链表最左边的头节点(即:有left为left,无left为根节点root)
/* function TreeNode(x) {
this.val = x;
this.left = null;
this.right = null;
} */
function Convert(root)
{
// write code here
if(!root) return null;
if(!root.left && !root.right) return root;
//构建左子树为双向链表,返回链表头节点left
var left = Convert(root.left);
var tmp = left;
//若左子树存在,则用tmp定位到左双向链表最后一个节点
while(tmp && tmp.right){
tmp = tmp.right;
}
//若左子树存在,将左双向链表最后一个节点和当前节点连接起来
//注意这里,tmp与left的存在与否完全相同
if(tmp){
tmp.right = root;
root.left = tmp;
}
//构建右子树为双向链表,返回链表头结点right
var right = Convert(root.right);
//将右双向链表头节点和当前节点连接起来
if(right){
right.left = root;
root.right = right;
}
//若有左子树,返回的永远是最左边的叶子节点(也就是最小的节点),若无左子树,则根节点就是最小的节点
return left?left:root;
}
- 解法二:
使用全局变量leftLast来表示左双向链表的最后一个节点(也就是上一种解法中的tmp)
/* function TreeNode(x) {
this.val = x;
this.left = null;
this.right = null;
} */
var leftLast;
function Convert(root)
{
// write code here
if(!root){
return null;
}
//返回最左边的头节点,并且此时左双向链表的最后一个节点也是该节点
if(root == null && root == null){
leftLast = root;
return root;
}
//构建左子树为双向链表,返回链表头节点left
var left = Convert(root.left);
//若左子树存在,则将左双向链表最后一个节点与当前节点连接起来
//这里,leftLast和left的存在与否并不完全一致哦!
if(left){
leftLast.right = root;
root.left = leftLast;
}
//那么此时不论有没有left,左双向链表的最后一个节点都是当前root啦
leftLast = root;
//构建右子树为双向链表,返回链表头结点right
var right = Convert(root.right);
//将右双向链表头节点和当前节点连接起来
if(right){
right.left = root;
root.right = right;
}
//若有左子树,返回的永远是最左边的叶子节点(也就是最小的节点),若无左子树,则根节点就是最小的节点
return left?left:root;
}