概述
题目描述:
输入一颗二叉搜索树,将二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
思路:
原先指向左子结点的指针调整为链表中指向前一个结点的指针,原先指向右子结点的指针指向为链表中指向后一个结点的指针。
由于要求转换后是排好序的链表,所以应该采用中序遍历的方法。
当遍历到根节点的时候,我们把树看成三部分
值为10的根结点,根结点值为6的左子树,根结点值为14的右子树。
我们需要把值为10的结点与左子树中最大的结点8, 右子树中最小的结点12连在一起。
package jianZhiOffer;
/*
* 面试题36:二叉搜素树与双向链表
* 题目:输入一棵二叉搜索树,将该二叉搜索树转换成一个排列的双向链表。
* 要求不能创建任何新的节点,只能调整树中节点指针的指向
*/
public class Demo36 {
static class TreeNode{
int value;
TreeNode left;
TreeNode right;
public TreeNode(int v) {
this.value = v;
}
}
public static TreeNode convert(TreeNode root){
TreeNode lastNodeInList = null;
convertNode(root, lastNodeInList);
if(lastNodeInList == null){
return null;
}
TreeNode listHead = lastNodeInList;
while(listHead != null && listHead.left != null){
listHead = listHead.left;
}
return listHead;
}
private static void convertNode(TreeNode node, TreeNode lastNodeInList) {
if(node == null){
return;
}
TreeNode currentNode = node;
if(currentNode.left != null){
convertNode(currentNode.left, lastNodeInList);
}
currentNode.left = lastNodeInList;
if(lastNodeInList != null){
lastNodeInList.right = currentNode;
}
lastNodeInList = currentNode;
if(lastNodeInList != null){
System.out.println("Set last = " + lastNodeInList.value);
}else{
System.out.println("Set last = null");
}
if(currentNode.right != null){
convertNode(currentNode.right, lastNodeInList);
}
}
public static void main(String[] args) {
TreeNode root = new TreeNode(10);
root.left = new TreeNode(6);
root.right = new TreeNode(14);
root.left.left = new TreeNode(4);
root.left.right = new TreeNode(8);
root.right.left = new TreeNode(12);
root.right.right = new TreeNode(16);
TreeNode head = convert(root);
}
}
通过栈的方法处理:
- 递归方法:
- 由于题目要求排序的双向列表,所以首先将二叉搜索树中序遍历,这里采用一个队列来存放要排序的节点,每访问一个节点将其
- 入队,最后全部入队后队列里面是排好序的节点,队首是值最小的节点。然后开始出队,每出队一个元素,将该元素的right指向
- 队首元素,将队首元素的left指向刚才出队的那个元素。直到队列中只有1个元素时,这时双向列表已经已经链接好了,但是题目里面唯一
- 提供的一个引用还在链表尾部,所以再将该引用通过循环指向双向链表头部那个最小的节点并返回,OK,我的这种方法应该是比较好理解的。
/*
* 递归方法:
* 由于题目要求排序的双向列表,所以首先将二叉搜索树中序遍历,这里采用一个队列来存放要排序的节点,每访问一个节点将其
* 入队,最后全部入队后队列里面是排好序的节点,队首是值最小的节点。然后开始出队,每出队一个元素,将该元素的right指向
* 队首元素,将队首元素的left指向刚才出队的那个元素。直到队列中只有1个元素时,这时双向列表已经已经链接好了,但是题目里面唯一
* 提供的一个引用还在链表尾部,所以再将该引用通过循环指向双向链表头部那个最小的节点并返回,OK,我的这种方法应该是比较好理解的。
*/
import java.util.LinkedList;
public class Solution {
public TreeNode Convert(TreeNode pRootOfTree) {
//创建一个空队列
LinkedList<TreeNode> queue=new LinkedList<TreeNode>();
if(pRootOfTree==null) return null;
else inRootTraverse(pRootOfTree, queue);
while(queue.size()>1){
pRootOfTree=queue.poll();//队首节点出队
pRootOfTree.right=queue.peek();
queue.peek().left=pRootOfTree;
}
//由于题目不让创建新的节点,而现在题目提供的引用指向列表尾部,所以只能将提供的引用指向链表首部
while(pRootOfTree.left!=null) pRootOfTree=pRootOfTree.left;
return pRootOfTree;
}
//中序遍历二叉搜索树
public void inRootTraverse(TreeNode root,LinkedList<TreeNode> queue){
if(root!=null){
inRootTraverse(root.left, queue);
queue.add(root);//入队
inRootTraverse(root.right, queue);
}
}
}
最后
以上就是可耐柠檬为你收集整理的【Java】面试题36:二叉搜索树与双向链表的全部内容,希望文章能够帮你解决【Java】面试题36:二叉搜索树与双向链表所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复