面试题27:二叉搜索数与双向链表

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

2.思路:


    由于要求转换之后的链表是排好序的,我们可以中序遍历树中的每一个结点,这是因为中序遍历算法的特点是按照从小到大的顺序遍历二叉树的每一个结点。

    最后,按照中序遍历的顺序,当我们遍历转换到根结点(值为10的结点)时,它的左子树已经转换成一个排序的链表了,并且处在链表中的最后一个结点是当前值最大的结点。我们把值为8的结点和根结点链接起来,此时链表中的最后一个结点就是10了。接着我们去遍历转换右子树,并把根结点和右子树中最小的结点链接起来。

  很明显,转换它的左子树和右子树,由于遍历和转换过程是一样的,很自然地想到可以用递归

3.java实现

递归

public BinaryTreeNode convert(BinaryTreeNode root) {
		BinaryTreeNode pre=null;//记录根节点前一个节点,即已转换链表的最后一个元素 
		pre=convertNode(root,pre);
		BinaryTreeNode head=pre;
		//System.out.println(head.left.value);
		while(head!=null&&head.left!=null) {
			head=head.left;
		}
		return head;
	}
	
	public BinaryTreeNode convertNode(BinaryTreeNode pNode,BinaryTreeNode pre) {
		if(pNode==null)
			return pre;
		//遍历左子树
		pre=convertNode(pNode.left,pre);
		//将当前节点连接到已排序的链表中
		pNode.left=pre;
		//链表末尾指针指向当前节点
		if(pre!=null) {
			pre.right=pNode;
		}
		//更新链表末尾指针为当前指针
		pre=pNode;
		//System.out.println(pre.value);
		//遍历右子树	
		pre=convertNode(pNode.right,pre);
		return pre;
	}

非递归:二叉搜索树的中序遍历是一个有序的数组,在中序遍历的时候,用 Pre 指针保存前一个节点,当访问到当前节点的时候,将 Pre 节点右指针,指向当前节点,当前节点的左指针指向 Pre。 这样中序遍历完二叉搜索树,就产生了一个双向链表。

public BinaryTreeNode convertWithStack(BinaryTreeNode root) {
		if(root==null)
			return null;
		BinaryTreeNode cur=root;
		BinaryTreeNode pre=null;
		Stack<BinaryTreeNode> stack=new Stack<BinaryTreeNode>();
		while(!stack.isEmpty()||cur!=null) {
			while(cur!=null) {
				stack.push(cur);
				cur=cur.left;
			}
			//到达树的最左边,出战
			cur=stack.pop();
			if(pre==null) {
				root=cur;//链表头结点
				pre=cur;
			}else {
				pre.right=cur;
				cur.left=pre;
				pre=cur;
			}
			cur=cur.right;
		}
		return root;
	}

用递归实现上面用栈实现的思路:

public class Solution{	
	BinaryTreeNode pre=null;
	BinaryTreeNode head=null;
	public BinaryTreeNode convert2(BinaryTreeNode root) {
		if(root==null)
			return null;
		convert2(root.left);
		if(pre==null) {
			root.left=pre;
			head=root;
			pre=root;
		}else {
			pre.right=root;
			root.left=pre;
			pre=root;
		}
		convert2(root.right);
		return head;
	}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值