如果有一个关键字的集合K={k0,k1,k2, ..., kn-1}, 把所有元素按完全二叉树的顺序存储
方式存放在一个一维数组中,并且满足
ki <= k2i+1 且 ki <= k2i+2 (i = 0, 1, ..., (n-2)/2 向上取整)
则称这个集合为小根堆。
创建
复制堆数组
找到最初的调整位置,即最后一个分支结点
自底向上逐步扩大形成堆
向前换一个分支结点
插入
将待插入元素插入已建成堆的最后面
沿着出入位置所在的分支逐步向上调整
删除
将顶元素删除
将数组中最后一个元素放到堆顶
自顶向下调整
代码实现
import java.util.Arrays;
/**
* Created by mico on 2017/2/5.
*/
public class HeapExam {
/**
* 小根堆初始化
*
* @param a
* @param length
*/
public void minHeap(int a[], int length) {
for (int i = length >> 1; i >= 0; i--) {
adjustMinHeap(a, length, i);
}
}
/**
* 排序 topn
*
* @param a
* @param length
*/
public void sort(int a[], int length) {
for (int i = 0, last = length; i < length - 1; i++) {
swap(a, 0, --last);
minHeap(a, last);
}
}
/**
* 小根堆调整
*
* @param a
* @param length
* @param i
*/
private void adjustMinHeap(int[] a, int length, int i) {
int left = 2 * i + 1;
int right = 2 * i + 2;
int minIndex = i;
if (left < length && a[left] < a[i]) {
minIndex = left;
}
if (right < length && a[right] < a[minIndex]) {
minIndex = right;
}
if (minIndex != i) {
swap(a, i, minIndex);
adjustMinHeap(a, length, minIndex);
}
}
/**
* 交换 数组值
*
* @param a
* @param i
* @param j
*/
private void swap(int[] a, int i, int j) {
a[i] = a[i] + a[j];
a[j] = a[i] - a[j];
a[i] = a[i] - a[j];
}
}
测试
public static void main(String[] args) {
int[] a = {153, 173, 728, 9, 425, 165, 7, 233};
//int[] arry_int={13, 38, 27, 55, 76, 65, 49, 97};
HeapExam exam = new HeapExam();
exam.minHeap(a, a.length);
System.out.println("小根堆:" + Arrays.toString(a));
exam.sort(a, a.length);
System.out.println("排序结果:" + Arrays.toString(a));
}
输出
小根堆:[7, 9, 153, 173, 425, 165, 728, 233]
排序结果:[728, 425, 233, 173, 165, 153, 9, 7]