面试算法001-- 把二元查找树转变成排序的双向链表

问题:

输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表, 

要求不能创建任何新的结点,只调整指针的指向 。

         10

        /      \
      6       14
     /  \       /   \

  4    8   12  16

  转换成 4->6->8->10->12->14->16

问题来源: 

本题是微软的面试题

问题分析:

一般与树有关的题目都可以用递归的思路来解决,本题我们也可以考虑用此思路来解决。

思路一:

每到一个节点时准备调整以该节点为根节点的子树(先调整其左子树,将左子树转换成一个排好序的左子链表,再调整其右子树,将其转换成右子链表,最后链接左子链表的最右端、当前节点、右子链表的最左端)。从树的根节点开始递归调整所有的节点。

思路二:

采用数的中序遍历整棵树。按这种方式比较小的节点会先被访问。如果我们每访问一个节点,假设之前访问过的节点已经调整成一个排序的双向链表,我们再把当前访问的阶段加入到其链表末尾。当所有的节点访问结束后,整棵树便变成了双向链表。

代码实现(Java):

public class Node<T extends Comparable<T>> {
	private T data;
	private Node<T> lNode;
	private Node<T> rNode;
	public Node(T data){
		this.setData(data);
		this.setlNode(null);
		this.setrNode(null);
	}
	/**
	 * @return the data
	 */
	public T getData() {
		return data;
	}
	/**
	 * @param data the data to set
	 */
	public void setData(T data) {
		this.data = data;
	}
	/**
	 * @return the lNode
	 */
	public Node<T> getlNode() {
		return lNode;
	}
	/**
	 * @param lNode the lNode to set
	 */
	public void setlNode(Node<T> lNode) {
		this.lNode = lNode;
	}
	/**
	 * @return the rNode
	 */
	public Node<T> getrNode() {
		return rNode;
	}
	/**
	 * @param rNode the rNode to set
	 */
	public void setrNode(Node<T> rNode) {
		this.rNode = rNode;
	}
	
}

/** 
 * @ClassName: BTree 
 * @Description: This class describe the binary tree
 * @author [email protected] 
 * @date Mar 2, 2015 2:01:53 PM 
 *  
 */
public class Tree<T extends Comparable<T>> {
	public Node<T> root = null;
	/**
	 * @Title: addNode 
	 * @Description: This method used to add a new node into the tree
	 * @param @param data
	 * @return void
	 * @throws
	 */
	public void addNode(T data){
		Node<T> node = new Node<T>(data);
		if(root == null){
			root = node;
		} else {
			Node<T> parent = root;
			Node<T> cur = root;
			boolean isLeft=true;
			while(cur != null)
			{
				parent=cur;
				if(data.compareTo(cur.getData()) < 0) {
					isLeft = true;
					cur = cur.getlNode();
				} else {
					isLeft=false;
					cur = cur.getrNode();
				}
			}
			if(isLeft) {
				parent.setlNode(node);
			} else
				parent.setrNode(node);
		}
	}

	/**
	 * 
	* @Title: display 
	* @Description: display all the nodes in tree
	* @param @param node
	* @return void
	* @throws
	 */
	public void display(Node<T> node){
		if(node != null){
			display(node.getlNode());
			System.out.print(node.getData() + "-->");
			display(node.getrNode());
		}
	}

}
public class List<T extends Comparable<T>> {
	/**
	 * 
	* @Title: append 
	* @Description: append two list
	* @param @param node1
	* @param @param node2
	* @param @return
	* @return Node<T>
	* @throws
	 */
	public Node<T> append(Node<T> node1,Node<T> node2)
	{
		if(node1==null)
			return node2;
		if(node2==null)
			return node1;
		Node<T> tail=node1;
		while(tail.getrNode()!=null) {
			tail=tail.getrNode();
		}
		tail.setrNode(node2);
		node2.setlNode(tail);
		return node1;
	}
	public void display(Node<T> node){
		while(node != null){
			System.out.print(node.getData() + "\t");
			node = node.getrNode();
		}
	}
}

public interface TreeToLinkList<T extends Comparable<T>> {
	public Node<T> convert(Node<T> root);
}

public class Test {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Tree<Integer> tree=new Tree<Integer>();
		tree.addNode(49);
		tree.addNode(25);
		tree.addNode(55);
		tree.addNode(10);
		tree.addNode(51);
		tree.addNode(65);
		tree.display(tree.root);
		System.out.println();
		TreeToLinkList<Integer> solution = new TreeToLinkListImpl1<Integer>();
		Node<Integer> node = solution.convert(tree.root);
		List<Integer> list = new List<Integer>();
		list.display(node);
		
		TreeToLinkList<Integer> solution2 = new TreeToLinkListImpl2<Integer>();
		Node<Integer> node2 = solution2.convert(tree.root);
		List<Integer> list2 = new List<Integer>();
		list2.display(node2);
	}

}


思路一代码:

public class TreeToLinkListImpl1<T extends Comparable<T>> implements TreeToLinkList<T>{

	/* (non-Javadoc)
	 * <p>Title: convert</p> 
	 * <p>Description: </p> 
	 * @param tree 
	 * @see Algorithm.Test.T001_TreeToLinkList.TreeToLinkList#convert(Algorithm.Test.T001_TreeToLinkList.Tree) 
	 */
	@Override
	public Node<T> convert(Node<T> root) {
		List<T> list = new List<T>();
		if(root != null){
			Node<T> left = convert(root.getlNode());
			Node<T> right = convert(root.getrNode());
			root.setlNode(null);
			root.setrNode(null);
			left = list.append(left, root);
			left = list.append(left, right);
			return left;
		} else {
			return null;
		}
	}

}


思路二代码:

/** 
 * @ClassName: TreeToLinkListImpl1 
 * @Description: The class implements the algorithm that convert the tree to link list
 * @author [email protected] 
 * @date Mar 2, 2015 4:24:31 PM 
 *  
 */
public class TreeToLinkListImpl2<T extends Comparable<T>> implements TreeToLinkList<T>{

	public Node<T> firstListNode;
	/* (non-Javadoc)
	 * <p>Title: convert</p> 
	 * <p>Description: </p> 
	 * @param tree 
	 * @see Algorithm.Test.T001_TreeToLinkList.TreeToLinkList#convert(Algorithm.Test.T001_TreeToLinkList.Tree) 
	 */
	@Override
	public Node<T> convert(Node<T> root) {
		inOrder(root);
		return this.firstListNode;
	}

	public void inOrder(Node<T> root){
		List<T> list = new List<T>();
		if(root.getlNode()!=null){
			inOrder(root.getlNode());
		}
		this.firstListNode = list.append(this.firstListNode, new Node<T>(root.getData()));
		if(root.getrNode()!=null){
			inOrder(root.getrNode());
		}
	}
}


你可能感兴趣的:(算法,面试题)