之前看了刘新宇大大的《算法新解》有了点收获,闲来无事,便写了一个二叉搜索树实现的Map类。
java的Map接口有很多不想要的方法,自己定义了一个
1 public interface IMap<K, V> { 2 V get(K k); 3 4 void put(K k, V v); 5 6 V remove(K k); 7 }
具体实现:
1 public class BSTree<K, V> implements IMap<K, V> { 2 Entry<K, V> head = null; 3 4 @Override 5 public V get(K k) { 6 return get(head, k); 7 } 8 9 private V get(Entry<K, V> node, K k) { 10 if (node == null) { 11 return null; 12 } 13 int compare = compare(node.key, k); 14 if (compare == 0) { 15 return node.value; 16 } else if (compare > 1) { 17 return get(node.right, k); 18 } else { 19 return get(node.left, k); 20 } 21 } 22 23 @Override 24 public void put(K k, V v) { 25 //1.head is null 26 if (head == null) { 27 head = new Entry<>(k, v, null); 28 } 29 //2.head is not null 30 else { 31 put(head, k, v); 32 } 33 } 34 35 private void put(Entry<K, V> node, K k, V v) { 36 int compare = compare(node.key, k); 37 if (compare == 0) { 38 node.value = v; 39 } else if (compare > 1) { 40 if (node.right == null) { 41 node.right = new Entry<>(k, null, node); 42 } 43 put(node.right, k, v); 44 } else { 45 if (node.left == null) { 46 node.left = new Entry<>(k, null, node); 47 } 48 put(node.left, k, v); 49 } 50 } 51 52 private int compare(K key, K k) { 53 return ((Comparable) key).compareTo(k); 54 } 55 56 @Override 57 public V remove(K k) { 58 return remove(head, k); 59 } 60 61 private V remove(Entry<K, V> node, K k) { 62 if (node == null) { 63 return null; 64 } 65 int compare = compare(node.key, k); 66 if (compare == 0) { 67 //1.no child 68 if (node.left == null && node.right == null) { 69 if (node.parent == null) 70 head = null; 71 else if (node == node.parent.left) { 72 node.parent.left = null; 73 } else { 74 node.parent.right = null; 75 } 76 return node.value; 77 } 78 //2.has right child 79 else if (node.right != null) { 80 V oldValue = node.value; 81 Entry<K, V> newNode = findMin(node.right); 82 node.key=newNode.key; 83 node.value = newNode.value; 84 newNode.parent.right = null; 85 return oldValue; 86 } 87 //3.has no right child,has left child 88 else{ 89 V oldValue = node.value; 90 Entry<K, V> newNode = findMax(node.left); 91 node.key=newNode.key; 92 node.value = newNode.value; 93 newNode.parent.left= null; 94 return oldValue; 95 } 96 97 } else if (compare > 0) { 98 return remove(node.right, k); 99 } else { 100 return remove(node.left, k); 101 } 102 } 103 104 private Entry<K, V> findMax(Entry<K, V> left) { 105 if (left.right == null) { 106 return left; 107 }else{ 108 return findMax(left.right); 109 } 110 } 111 112 private Entry<K, V> findMin(Entry<K, V> right) { 113 if (right.left == null) { 114 return right; 115 }else { 116 return findMin(right.left); 117 } 118 } 119 120 class Entry<K, V> { 121 K key; 122 V value; 123 Entry<K, V> left; 124 Entry<K, V> right; 125 Entry<K, V> parent; 126 127 private Entry(K key, V value, Entry<K, V> parent) { 128 this.key = key; 129 this.value = value; 130 left = null; 131 right = null; 132 this.parent = parent; 133 } 134 } 135 136 }
测试的类:
1 public class BSTreeTest { 2 private static int write_num = 100_0000; 3 private static int read_num = 100_0000; 4 5 public static void main(String[] args) { 6 // IMap<String,Integer> map = new BSTree(); 7 // Map<String, Integer> map = new TreeMap<>(); 8 // Map<String, Integer> map = new HashMap<>(); 9 Map<String, Integer> map = new LinkedHashMap<>(); 10 long start = System.nanoTime(); 11 for (int i = 0; i < write_num; i++) { 12 map.put("" + i, i); 13 } 14 for (int i = 0; i < read_num; i++) { 15 Integer s = map.get(i + ""); 16 assert s.equals(i); 17 } 18 for (int i = 0; i < read_num / 2; i++) { 19 map.remove(i + ""); 20 } 21 for (int i = 0; i < read_num / 2; i++) { 22 Integer s = map.get(i + ""); 23 assert s == null; 24 } 25 for (int i = read_num / 2; i < read_num / i++; i++) { 26 Integer s = map.get(i + ""); 27 assert s.equals(i); 28 } 29 System.out.println("map cost:" + (System.nanoTime() - start)); 30 } 31 }
在各自只运行一次的情况下测试数据如下:
map cost:1125174394 //myMap map cost:812963047 //TreeMap map cost:475993738 //HashMap map cost:475993738 //LinkedHashMap
由于二叉搜索树没有自平衡机制,搜索的时间在O(n)与O(lgn)之间摇摆,因此对比java用红黑树实现的TreeMap时间O(lgn)要多上很多。