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 }