Java实现: 把二元查找树转变成排序的双向链表(树)

题目

        输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。要求不能创建任何新的结点,只调整指针的指向。

            10

            /    \
          6      14

        /   \     /   \

      4    8  12   16

转换成双向链表4=6=8=10=12=14=16

首先我们定义的二元查找树 节点的数据结构如下:

struct BSTreeNode{

    int m_nValue; // value of node

  BSTreeNode *m_pLeft;// left child of node

  BSTreeNode *m_pRight;// right child of node

};


解题思路
        熟悉二叉树中序展示的同学都知道,对于当前节点,先展示左子结点,然后展示自己,最后展示有子节点,使用这样的递归就完成二叉树的中序展示。
同理,这个算法同样使用上述方式完成,但是需要明白以下三点:
1.当前节点的最小子节点,也就是当前节点构成的双向链表的头元素为,当前元素的左子叶子节点。
2.当前节点构造的双向链表的下一个元素为,当前节点的右子节点的最小节点,见1.
3.当前节点构造的双向链表的上一个元素为,上一次操作的节点。

代码如下:
public class BSTreeNode {
	private Integer value;
	private BSTreeNode leftNode;
	private BSTreeNode rightNode;

	/**
	 * 插入节点。
	 * @param value
	 */
	public void add(int value) {
		if (this.value == null) {
			this.value = value;
		} else if (this.value > value) {
			if (leftNode == null){
				leftNode = new BSTreeNode();
				leftNode.value = value;
			} else {
				leftNode.add(value);
			}
		} else if (this.value < value) {
			if (rightNode == null){
				rightNode = new BSTreeNode();
				rightNode.value = value;
			} else {
				rightNode.add(value);
			}
		}
	}
	
	/**
	 * 中序遍历所有节点
	 */
	public List<BSTreeNode> list(){
		List<BSTreeNode> result = new ArrayList<BSTreeNode>();
		if (this.value == null){
			return result;
		}
		if (leftNode != null){
			result.addAll(leftNode.list());
		}
		result.add(this);
		if (rightNode != null){
			result.addAll(rightNode.list());
		}
		return result;
	}
	
	public BSTreeNode convertLinkedList(){
		Map<String, BSTreeNode> map = new HashMap<String, BSTreeNode>();
		doConvertLinkedList(map);
		return map.get("headNode");
	}
	
	private void doConvertLinkedList(Map<String, BSTreeNode> map){
		if (leftNode != null){
			leftNode.doConvertLinkedList(map);
		}
		handleCurrentNode(map);
		if (rightNode != null){
			rightNode.doConvertLinkedList(map);
		}
	}
	
	private void handleCurrentNode(Map<String, BSTreeNode> map){
		BSTreeNode lastNode = map.get("lastNode");
		this.leftNode = lastNode;
		if (lastNode == null){
			map.put("headNode", this);
		} else {
			lastNode.rightNode = this;
		}
		map.put("lastNode", this);
	}
	
	public Integer getValue(){
		return this.value;
	}
	
	public BSTreeNode getLeftNode(){
		return this.leftNode;
	}
	
	public BSTreeNode getRightNode(){
		return this.rightNode;
	}
}

jUnit测试如下

public class BSTreeNodeTest {

	@Test
	public void testAdd(){
		BSTreeNode root = new BSTreeNode();
		root.add(10);
		assertEquals(root.getValue(), Integer.valueOf(10));
		root.add(20);
		assertEquals(root.getRightNode().getValue(), Integer.valueOf(20));
		root.add(30);
		assertEquals(root.getRightNode().getRightNode().getValue(), Integer.valueOf(30));
		root.add(25);
		assertEquals(root.getRightNode().getRightNode().getLeftNode().getValue(), Integer.valueOf(25));
	}
	
	@Test
	public void testList() {
		BSTreeNode root = new BSTreeNode();
		List<Integer> valueList = new ArrayList<Integer>();
		valueList.add(10);
		valueList.add(20);
		valueList.add(30);
		valueList.add(25);
		for (Integer value : valueList){
			root.add(value.intValue());
		}
		List<BSTreeNode> nodeList = root.list();
		Collections.sort(valueList);
		for (int i = 0; i < nodeList.size(); i++){
			BSTreeNode node = nodeList.get(i);
			assertEquals(node.getValue(), valueList.get(i));
		}
	}
	
	@Test
	public void testConvertLinkedList(){
		BSTreeNode root = new BSTreeNode();
		int count = 100;
		Random random = new Random();
		List<Integer> valueList = new ArrayList<Integer>();
		for (int i = 0; i < count; i++){
			int value = random.nextInt(1000);
			if (!valueList.contains(value)){
				valueList.add(value);
			}
		}
		for (Integer value : valueList){
			root.add(value.intValue());
		}
		Collections.sort(valueList);
		BSTreeNode currentNode = root.convertLinkedList();
		for (int i = 0; i < valueList.size(); i++){
			assertEquals(currentNode.getValue(), valueList.get(i));
			currentNode = currentNode.getRightNode();
		}
	}

}





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值