-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathMinHeap.java
131 lines (102 loc) · 3.28 KB
/
MinHeap.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import java.util.*;
public class MinHeap<E extends Comparable<E>> {
private Array<E> data;
public MinHeap(int capacity){
data = new Array<>(capacity);
}
public MinHeap(){
data = new Array<>();
}
public MinHeap(E[] arr){
data = new Array<>(arr);
if(arr.length != 1){
for(int i = parent(arr.length - 1) ; i >= 0 ; i --)
siftDown(i);
}
}
// 返回堆中的元素个数
public int size(){
return data.getSize();
}
// 返回一个布尔值, 表示堆中是否为空
public boolean isEmpty(){
return data.isEmpty();
}
// 返回完全二叉树的数组表示中,一个索引所表示的元素的父亲节点的索引
private int parent(int index){
if(index == 0)
throw new IllegalArgumentException("index-0 doesn't have parent.");
return (index - 1) / 2;
}
// 返回完全二叉树的数组表示中,一个索引所表示的元素的左孩子节点的索引
private int leftChild(int index){
return index * 2 + 1;
}
// 返回完全二叉树的数组表示中,一个索引所表示的元素的右孩子节点的索引
private int rightChild(int index){
return index * 2 + 2;
}
// 向堆中添加元素
public void add(E e){
data.addLast(e);
siftUp(data.getSize() - 1);
}
private void siftUp(int k){
// !!!
while(k > 0 && data.get(parent(k)).compareTo(data.get(k)) > 0 ){
data.swap(k, parent(k));
k = parent(k);
}
}
// !!!
// 看堆中的最小元素
public E findMin(){
if(data.getSize() == 0)
throw new IllegalArgumentException("Can not findMax when heap is empty.");
return data.get(0);
}
// 取出堆中最小元素
public E extractMin(){
E ret = findMin();
data.swap(0, data.getSize() - 1);
data.removeLast();
siftDown(0);
return ret;
}
private void siftDown(int k){
while(leftChild(k) < data.getSize()){
int j = leftChild(k); // 在此轮循环中,data[k]和data[j]交换位置
// !!!
if( j + 1 < data.getSize() &&
data.get(j + 1).compareTo(data.get(j)) < 0 )
j ++;
// data[j] 是 leftChild 和 rightChild 中的最小值
// !!!
if(data.get(k).compareTo(data.get(j)) <= 0 )
break;
data.swap(k, j);
k = j;
}
}
// 取出堆中的最小元素,并且替换成元素e
public E replace(E e){
E ret = findMin();
data.set(0, e);
siftDown(0);
return ret;
}
public static void main(String[] args) {
int n = 1000000;
MinHeap<Integer> minHeap = new MinHeap<>();
Random random = new Random();
for(int i = 0 ; i < n ; i ++)
minHeap.add(random.nextInt(Integer.MAX_VALUE));
int[] arr = new int[n];
for(int i = 0 ; i < n ; i ++)
arr[i] = minHeap.extractMin();
for(int i = 1 ; i < n ; i ++)
if(arr[i-1] > arr[i])
throw new IllegalArgumentException("Error");
System.out.println("Test MinHeap completed.");
}
}