微软算法100题01 二叉搜索树转为双向链表
提高编程能力的最佳途径就是多写代码, 就让我们从现在开始吧!
1. 输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。
要求不能创建任何新的结点,只调整指针的指向。
10
/ |
6 14
/ | / |
4 8 12 16
转换成双向链表
4=6=8=10=12=14=16。
二叉查找树的特点:任意节点的左子树都要小于当前节点;右子树都要大于当前节点。
特点:查询某个值,需要的时间复杂度为O(lgN)
网上的解决方案大部分都是C的, 我给出一个JAVA的吧
我的思路: 如果要把一颗二叉树转换为已排序的双向链表,则在双向链表中,根节点的左子树必然在根节点的前面,根节点的右子树必然在根节点的后面,根节点的直接前缀节点必然为左子树中最大的节点,根节点的直接后缀节点必然为右子树中最小的节点,
1. 找到根节点的左子树,找到其最大节点,作为根节点的前缀节点
2. 找到根节点的右子树,找到其最小节点,作为根节点的后缀节点
3.如果左子树不是叶子节点,则用1和2 的逻辑递归处理该左子树
4.如果右子树不是叶子节点,则用1和2 的逻辑递归处理该右子树
1 package com.rui.microsoft; 2 3 /** 4 * 5 * 6 * 把二元查找树转变成排序的双向链表 7 题目: 8 输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。 9 要求不能创建任何新的结点,只调整指针的指向。 10 10 11 / \ 12 5 15 13 / \ / \ 14 3 6 13 16 15 转换成双向链表 16 3=5=6=10=13=15=16 17 */ 18 public class Test01 { 19 20 public static void main(String[] args) { 21 Test01 test = new Test01(); 22 Node root = test.initTree(); 23 Node head = test.convertToDoubleLink(root); 24 while(null != head){ 25 System.out.print(" " + head.getValue()); 26 head = head.getRight(); 27 } 28 } 29 30 private boolean isLeaf(Node node){ 31 if(null == node.getLeft() && null == node.getRight()) return true; 32 else return false; 33 } 34 35 private Node findMin(Node node){ 36 if(null == node) return null; 37 if(null == node.getLeft()) return node; 38 return findMin(node.getLeft()); 39 } 40 41 private Node findMax(Node node){ 42 if(null == node) return null; 43 if(null == node.getRight()) return node; 44 return findMin(node.getRight()); 45 } 46 47 public Node convertToDoubleLink(Node node){ 48 if(null == node) return null; 49 50 Node head = findMin(node); 51 52 //Find the node directly before current node in the double link 53 Node leftNode = findMax(node.getLeft()); 54 55 //Find the node directly after current node in the double link 56 Node rightNode = findMin(node.getRight()); 57 58 //Process left 59 if(null != node.getLeft()){ 60 processLeftTree(node.getLeft(), node); 61 } 62 63 //Process right 64 if(null != node.getRight()){ 65 processRightTree(node.getRight(), node); 66 } 67 68 //Relocate leftNode according to double link to the left side of current node 69 if(null != leftNode){ 70 leftNode.setRight(node); 71 node.setLeft(leftNode); 72 } 73 74 //Relocate rightNode according to double link to the right side of current node 75 if(null != rightNode){ 76 rightNode.setLeft(node); 77 node.setRight(rightNode); 78 } 79 80 return head; 81 } 82 83 private void processRightTree(Node right, Node node) { 84 if(isLeaf(right)){ 85 right.setLeft(node); 86 return; 87 } 88 convertToDoubleLink(right); 89 } 90 91 private void processLeftTree(Node left, Node node) { 92 if(isLeaf(left)){ 93 left.setRight(node); 94 return; 95 } 96 convertToDoubleLink(left); 97 } 98 99 private Node initTree(){ 100 Node root = new Node(); 101 root.setValue(10); 102 103 Node node01 = new Node(); 104 node01.setValue(5); 105 106 Node node011 = new Node(); 107 node011.setValue(3); 108 109 Node node012 = new Node(); 110 node012.setValue(6); 111 112 node01.setLeft(node011); 113 node01.setRight(node012); 114 115 root.setLeft(node01); 116 117 Node node02 = new Node(); 118 node02.setValue(15); 119 120 Node node021 = new Node(); 121 node021.setValue(13); 122 123 Node node022 = new Node(); 124 node022.setValue(16); 125 126 node02.setLeft(node021); 127 node02.setRight(node022); 128 129 root.setRight(node02); 130 return root; 131 } 132 133 134 class Node { 135 136 private int value; 137 private Node left; 138 private Node right; 139 140 /** 141 * @return the value 142 */ 143 public int getValue() { 144 return value; 145 } 146 /** 147 * @param value the value to set 148 */ 149 public void setValue(int value) { 150 this.value = value; 151 } 152 /** 153 * @return the left 154 */ 155 public Node getLeft() { 156 return left; 157 } 158 /** 159 * @param left the left to set 160 */ 161 public void setLeft(Node left) { 162 this.left = left; 163 } 164 /** 165 * @return the right 166 */ 167 public Node getRight() { 168 return right; 169 } 170 /** 171 * @param right the right to set 172 */ 173 public void setRight(Node right) { 174 this.right = right; 175 } 176 } 177 }