二项堆
1 public class BinaryHeap<E extends Comparable<? super E>> 2 { 3 4 public static void main(String[] args) 5 { 6 Integer[] array = {0, 12, 90, 1, 85, 12, 3, 13, 49, 7 55, 10, 3, 31, 97, 19, 93, 41, 55, 56, 82, 2}; 8 9 BinaryHeap<Integer> heap = new BinaryHeap<Integer>(); 10 11 for (int i = 0; i < array.length; i++) { 12 heap.insert(array[i]); 13 } 14 15 heap.traversal(heap.head); 16 System.out.println(); 17 18 Integer item = (Integer) heap.find(new Integer(55)); 19 20 if (item == null) 21 System.out.println("节点不存在"); 22 else 23 System.out.println("要找的节点为" + item.toString()); 24 25 System.out.println(heap.findMinNode().value); 26 27 heap.traversal(); 28 heap.delete(new Integer(31), new Integer(-Integer.MIN_VALUE)); 29 System.out.println(); 30 heap.traversal(); 31 } 32 33 34 HeapNode head = null; 35 36 /* 37 * 查询最小关键字节点 38 * 由于二项堆中每个二项树都遵循最小堆性质, 39 * 从heap节点依次遍历其兄弟节点,找出最小关键字节点 40 */ 41 private HeapNode findMinNode() 42 { 43 if (head == null) return null; 44 45 HeapNode node = head, min = head; 46 47 while (node != null) { 48 int compare = min.value.compareTo(node.value); 49 if (compare > 0) min = node; 50 node = node.sibling; 51 } 52 return min; 53 } 54 55 /* 56 * 插入节点 57 */ 58 public void insert(E value) 59 { 60 if (value == null) return; 61 62 HeapNode node = new HeapNode(value); 63 BinaryHeap<E> bh = new BinaryHeap<E>(); 64 bh.head = node; 65 union(bh); 66 } 67 68 /* 69 * 合并节点 70 */ 71 public void merge(BinaryHeap<E> heap) 72 { 73 HeapNode node; 74 HeapNode head1 = this.head; 75 HeapNode head2 = heap.head; 76 77 // 确定head 78 if (head1.degree < head2.degree) { 79 node = head1; 80 head1 = head.sibling; 81 } 82 else { 83 this.head = head2; 84 node = head2; 85 head2 = head2.sibling; 86 } 87 88 // 归并合并二项堆 89 while (head1 != null && head2 != null) { 90 if (head1.degree < head2.degree) { 91 node.sibling = head1; 92 node = head1; 93 head1 = head1.sibling; 94 } 95 else { 96 node.sibling = head2; 97 node = head2; 98 head2 = head2.sibling; 99 } 100 } 101 102 node.sibling = (head1 == null) ? head2 : head1; 103 } 104 105 /* 106 * 查找节点 107 */ 108 private HeapNode find(E value, HeapNode node) 109 { 110 if (node == null) return null; 111 if (value.compareTo(node.value) == 0) return node; 112 113 HeapNode node1 = find(value, node.sibling); 114 HeapNode node2 = find(value, node.child); 115 116 if (node1 != null) return node1; 117 if (node2 != null) return node2; 118 return null; 119 } 120 121 /* 122 * 查询节点 123 */ 124 public E find(E value) 125 { 126 HeapNode node = find(value, head); 127 if (node == null) return null; 128 return node.value; 129 } 130 131 /* 132 * 合并二项堆 133 * 将this和heap合并成一个新二项堆 134 */ 135 private void union(BinaryHeap<E> heap) 136 { 137 if (heap.head == null) return; 138 if (this.head == null) { 139 this.head = heap.head; 140 return; 141 } 142 143 merge(heap); 144 145 HeapNode prev = null; 146 HeapNode node = this.head; 147 HeapNode next = node.sibling; 148 /* 149 * 情况1 degree[x] != degree[next], x为B-k书的根,next为B-l书的根且l > k 150 * 动作 将指针移向表中下一个位置 151 * 152 * 情况2 degree[x] = degree[next] = degree[sibling[next]] 153 * 动作 将指针移向表中下一个位置,下一次迭代将执行情况3或4,将第二和第三个根联合起来 154 * 155 * 情况3 x为具有相同度数的两个根中的第一个发生时 156 * degree[x] = degree[next] != degree[sibling[next]] 157 * 动作 value[x] <= value[next] 将next连接到x上作为x的左孩子 158 * 159 * 情况4 x为具有相同度数的两个根中的第一个发生时 160 * degree[x] = degree[next] != degree[sibling[next]] 161 * 动作 value[x] > value[next] 将x连接到next上作为next的左孩子 162 */ 163 while (next != null) { 164 if ((node.degree != next.degree) || 165 (next.sibling != null && next.sibling.degree == node.degree)) { 166 prev = node; 167 node = next; 168 } 169 else if (node.value.compareTo(next.value) <= 0) { 170 node.sibling = next.sibling; 171 link(next, node); 172 } 173 else { 174 if (prev == null) { 175 this.head = next; 176 } 177 else { 178 prev.sibling = next; 179 } 180 link(node, next); 181 node = next; 182 } 183 next = node.sibling; 184 } 185 } 186 187 public void delete(E value, E min) 188 { 189 HeapNode node = find(value, head); 190 if (node == null) return; 191 decreaseKey(value, min); 192 extractMin(); 193 } 194 195 /* 196 * 减小某解点的值 197 */ 198 private void decreaseKey(E source, E target) 199 { 200 HeapNode node = find(source, head); 201 if (node == null) return; 202 node.value = target; 203 HeapNode parent = node.parent; 204 205 while (parent != null && 206 node.value.compareTo(parent.value) < 0) 207 { 208 // 交换当前结点与父节点的值 209 E temp = node.value; 210 node.value = parent.value; 211 parent.value = temp; 212 213 node = parent; 214 parent = parent.parent; 215 } 216 } 217 218 /* 219 * 抽取关键字最小的节点 220 */ 221 private void extractMin() 222 { 223 HeapNode min = findMinNode(); 224 HeapNode minPrev = head; 225 226 // 独立最小值所在二项数 227 if (min != head) { 228 while (minPrev.sibling != min) { 229 minPrev = minPrev.sibling; 230 } 231 minPrev.sibling = min.sibling; 232 } 233 else { 234 head = head.sibling; 235 } 236 min.sibling = null; 237 238 BinaryHeap<E> bh = new BinaryHeap(); 239 240 // 将min与子节点分离 241 HeapNode child = min.child; 242 child.parent = min.child = null; 243 244 // 245 HeapNode prev, node, next; 246 prev = child; 247 node = child.sibling; 248 prev.sibling = null; 249 250 while (node != null) { 251 next = node.sibling; 252 node.parent = null; 253 node.sibling = prev; 254 prev = node; 255 node = next; 256 } 257 258 bh.head = prev; 259 260 // 将分离出来的二项堆与原来的合并 261 union(bh); 262 } 263 264 /* 265 * 连接两个节点 266 */ 267 private void link(HeapNode big, HeapNode small) 268 { 269 big.parent = small; 270 big.sibling = small.child; 271 small.child = big; 272 small.degree++; 273 } 274 275 public void traversal(HeapNode node) 276 { 277 if (node == null) return; 278 System.out.print(node.value + ","); 279 traversal(node.sibling); 280 traversal(node.child); 281 } 282 283 /* 284 * 遍历二项堆 285 */ 286 public void traversal() 287 { 288 traversal(head); 289 } 290 291 292 class HeapNode 293 { 294 private HeapNode parent; 295 296 private HeapNode sibling; 297 298 private HeapNode child; 299 300 private E value; 301 302 private int degree = 0; 303 304 305 public HeapNode(E value) 306 { 307 this.value = value; 308 } 309 } 310 }