先看一下调整好的小根堆和大根堆
下面举一个调整的例子
下面是一个实际的问题:数据流中的中位数
题目描述:
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
import java.util.ArrayList;
public class BuilderHeap {
void adjustMaxHeap(ArrayList<Integer> array, int parent) {
// array[0 ~ size-1]
int lchild = 2 * parent + 1;
int rchild = 2 * parent + 2;
int max = parent;
int size = array.size();
if (parent < size / 2) {
if (lchild < size && array.get(lchild) > array.get(max))
max = lchild;
if (rchild < size && array.get(rchild) > array.get(max))
max = rchild;
if (max != parent) {
int tmp = array.get(parent);
array.set(parent, array.get(max));
array.set(max, tmp);
adjustMaxHeap(array, max);
}
}
}
void adjustMinHeap(ArrayList<Integer> array, int parent) {
// array[0 ~ size-1]
int lchild = 2 * parent + 1;
int rchild = 2 * parent + 2;
int min = parent;
int size = array.size();
if (parent < size / 2) {
if (lchild < size && array.get(lchild) < array.get(min))
min = lchild;
if (rchild < size && array.get(rchild) < array.get(min))
min = rchild;
if (min != parent) {
int tmp = array.get(parent);
array.set(parent, array.get(min));
array.set(min, tmp);
adjustMaxHeap(array, min);
}
}
}
ArrayList<Integer> minArray = new ArrayList<>();
ArrayList<Integer> maxArray = new ArrayList<>();
public void Insert(Integer num) {
if (((minArray.size() + maxArray.size()) & 1) == 1) { // 已经插入奇数个
if (minArray.size() + maxArray.size() >= 3) {
if (num > maxArray.get(0)) { // insert into maxArray
minArray.add(maxArray.get(0));
// update max
maxArray.set(0, num);
adjustMinHeap(maxArray, 0);
} else { // insert into minArray
minArray.add(num);
}
// update minArray
for (int i = minArray.size() / 2 - 1; i >= 0; --i) {
adjustMaxHeap(minArray, i);
}
} else {
if (num > maxArray.get(0)) { // insert into maxArray
minArray.add(maxArray.get(0));
// update max
maxArray.set(0, num);
} else { // insert into minArray
minArray.add(num);
}
}
} else { // 已经插入偶数个
if (minArray.size() + maxArray.size() >= 2) {
if (num > minArray.get(0)) { // insert into maxArray
// update max
maxArray.add(num);
} else {
maxArray.add(minArray.get(0));
minArray.set(0, num);
adjustMaxHeap(minArray, 0);
}
// update maxArray
for (int i = maxArray.size() / 2 - 1; i >= 0; --i) {
adjustMinHeap(maxArray, i);
}
} else {
maxArray.add(num);
}
}
}
public Double GetMedian() {
if (((minArray.size() + maxArray.size()) & 1) == 1) { // 已经插入奇数个
return 1.0 * maxArray.get(0);
} else if (maxArray.size() + minArray.size() > 0) {
return (maxArray.get(0) + minArray.get(0)) / 2.0;
}
return 0.0;
}
public static void main(String[] args) {
BuilderHeap heap = new BuilderHeap();
int[] vals = new int[] { 5, 2, 3, 4, 1, 6, 7, 0, 8 };
for (int i = 0; i < vals.length; ++i) {
heap.Insert(vals[i]);
System.out.println(heap.maxArray);
System.out.println(heap.minArray);
System.out.println(heap.GetMedian());
}
}
}