【Java】面试题36:二叉搜索树与双向链表

题目描述:

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

思路:

原先指向左子结点的指针调整为链表中指向前一个结点的指针,原先指向右子结点的指针指向为链表中指向后一个结点的指针。

由于要求转换后是排好序的链表,所以应该采用中序遍历的方法。
当遍历到根节点的时候,我们把树看成三部分
值为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);
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值