package leetcode.heap;
/**
* 小顶堆(即根节点小于或等于左右子树的值,且左右子树也为小顶堆) <br>
* 堆是满二叉树,有特殊的性质
* <ul>
* <li>1、对于节点在i的元素,其左儿子在位置2i上,右儿子的2i+1上</li>
* <li>2、父亲节点在i/2向下取整的位置上</li>
* </ul>
*
* @author li
*
*/
public class MinHeap {
private int size;
private final int MAX_CAPACITY;
private int[] num;
public int[] getNum() {
return num;
}
public MinHeap(int capacity) {
this.size = 0;
this.MAX_CAPACITY = capacity;
num = new int[MAX_CAPACITY + 1];
}
/**
* 堆的插入: 采用向上过滤的方法<br>
* 从数组的第二个元素进行插入
*
* @param value
* @throws Exception
*/
public void insert(int value) throws Exception {
if (size > MAX_CAPACITY) {
throw new Exception("已经超出范围");
}
int i;
for (i = (++size); num[i / 2] > value; i = i / 2) {
num[i] = num[i / 2];
}
num[i] = value;
}
public int getMin() {
return num[1];
}
/**
* 删除堆顶元素 <br>
* <ul>
* <li>递归的找到每个节点左右子树的最小值</li>
* <li>将该最小值填充到父节点</li>
* </ul>
*
* @throws Exception
*/
public int deleteMin() throws Exception {
if (size == 0) {
throw new Exception("已经为空");
}
int LastElement = num[size--];// 获取最后一个元素,并且size-1
int minElement = num[1];
int child, i;
for (i = 1; i * 2 <= size; i = child) {
child = 2 * i;
if (child != size && num[child + 1] < num[child]) {
child++;// 右子树小于左子树
}
if (LastElement > num[child]) {
num[i] = num[child];
} else {
break;
}
}
num[i] = LastElement;
return minElement;
}
public static void main(String[] args) {
MinHeap minHeap = new MinHeap(5);
try {
minHeap.insert(4);
minHeap.insert(2);
minHeap.insert(3);
minHeap.insert(2);
minHeap.insert(2);
int[] num = minHeap.num;
for (int i = 0; i < num.length; i++) {
System.out.println(num[i]);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
package leetcode.heap;
/**
*
* @author li
*
*/
public class FindMaxK {
/**
* 寻找最大的k个数<br>
* 利用小顶堆来实现<br>
* 建立k个节点的小顶堆<br>
* 接着遍历,如果数字大于堆顶元素,则删除堆顶元素,并插入新的元素,遍历完成后堆中的元素即为最大的k个元素
*
* @param num
* @throws Exception
*/
public int[] findMaxK(int[] num, int k) throws Exception {
if (num.length <= k) {
return num;
}
MinHeap minHeap = new MinHeap(k);
for (int i = 0; i < k; i++) {
minHeap.insert(num[i]);
}
for (int i = k; i < num.length; i++) {
if (num[i] > minHeap.getMin()) {
minHeap.deleteMin();
minHeap.insert(num[i]);
}
}
return minHeap.getNum();
}
public static void main(String[] args) {
int[] num = { 4, 54, 32, 1, 4, 66, 87, 34 };
try {
int[] maxk = new FindMaxK().findMaxK(num, 4);
for (int i = 1; i < maxk.length; i++) {
System.out.println(maxk[i]);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}