首先介绍一下什么是堆:
引入百度百科:
(英语:heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵树的数组对象。堆总是满足下列性质:
堆中某个节点的值总是不大于或不小于其父节点的值;
堆总是一棵完全二叉树。
将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。常见的堆有二叉堆、斐波那契堆等。
堆的定义如下:n个元素的序列{k1,k2,ki,…,kn}当且仅当满足下关系时,称之为堆。
(ki <= k2i,ki <= k2i+1)或者(ki >= k2i,ki >= k2i+1), (i = 1,2,3,4…n/2)
若将和此次序列对应的一维数组(即以一维数组作此序列的存储结构)看成是一个完全二叉树,则堆的含义表明,完全二叉树中所有非终端结点的值均不大于(或不小于)其左、右孩子结点的值。由此,若序列{k1,k2,…,kn}是堆,则堆顶元素(或完全二叉树的根)必为序列中n个元素的最小值(或最大值)
简单概括:
1.堆一定是完全二叉树。
2.大(小)顶堆中当前结点的值一定大(小)于其左右孩子的值。
下图为大顶堆和小顶堆:
给出堆的建立以及排序实现:
/**
* 堆
* @author zxy
*
*/
public class Heap {
private int[] array;
private int count; //堆中元素的个数
private int capacity; //堆的大小
private int heap_type; //大顶堆或小顶堆 0大 1小
public Heap(int capacity, int heap_type){
this.heap_type=heap_type;
this.count=0;
this.capacity=capacity;
this.array=new int[capacity];
}
/**
* 获取父结点
* @param i
* @return
*/
public int parent(int i){
if(i<=0 || i>=this.count){
return -1;
}
return (i-1)/2;
}
/**
* 获取左孩子
* @param i
* @return
*/
public int leftChild(int i){
int left=2*i+1;
if(left>=this.count){
return -1;
}
return left;
}
/**
* 获取右孩子
* @param i
* @return
*/
public int rightChild(int i){
int right=2*i+2;
if(right>=this.count){
return -1;
}
return right;
}
/**
* 获取堆中最大值(大顶堆的根结点)
* @return
*/
public int getMaximum(){
if(this.count==0){
return -1;
}
return array[0];
}
/**
* 向下调整(当前结点与左右孩子较大值的结点换位,保证三个结点的最大值处于上位)
* @param i
*/
public void percolateDown(int i){
int l,r,max,temp;
l=leftChild(i);
r=rightChild(i);
if(l!=-1 && this.array[l]>this.array[i]){
max=l;
}else{
max=i;
}
if(r!=-1 && this.array[r]>this.array[max]){
max=r;
}
if(max!=i){
temp=this.array[i];
this.array[i]=this.array[max];
this.array[max]=temp;
percolateDown(max);
}
}
/**
* 建堆,从最后一个叶子结点的父结点开始向下调整
* @param h
* @param a
* @param n
*/
public static void build(Heap h,int a[],int n){
h.array=a;
h.count=n;
for(int i=(n-2)/2;i>=0;i--){
h.percolateDown(i);
}
}
/**
* 堆排序
* 每趟排序将最后一个结点与根结点换位,再将根结点向下调整,并且堆大小减1
* 因为大顶堆的根结点是最大值,所以每趟排序过后,当前堆的最大值移至末尾
* 所有排序结束,堆中元素呈现从小到大
* @param a
* @param n
*/
public static void sort(int a[],int n){
Heap h=new Heap(n,0);
int old_size,i,temp;
build(h, a, n);
old_size=h.count;
for(i=n-1;i>0;i--){
temp=h.array[0];
h.array[0]=h.array[i];
h.array[i]=temp;
h.count--;
h.percolateDown(0);
}
h.count=old_size;
a=h.array;
}
/**
* 测试
* @param args
*/
public static void main(String[] args) {
int[] array=new int[]{1,4,2,5,13,6,17};
Heap.sort(array, array.length);
for(int i=0;i<array.length;i++){
System.out.print(array[i]+" ");
}
}
}