简介:
堆的特征是:堆顶元素是所有元素的最优值。堆的应用有堆排序和优先队列。
堆有两种:最大堆、最小堆。最大堆的根结点元素有最大值,最小堆的根结点元素有最小值。时间复杂度为O(logn)。下面都以最小堆为例进行讲解。
操作:
入堆:每次把元素放进堆,都调整堆的形状,使得根结点保持最小。
出堆:每次取出的堆顶,就是整个堆的最小值;同时调整堆,使得新的堆顶最小。
存储结构:
用数组array[]存储完全二叉树,结点数量为n,array[0]不用,array[1]为根结点,有以下性质:
(1)i > 1的结点,其父结点位于i/2;
(2)如果2i > n,那么i没有孩子;如果2i+1 > n,那么i没有右孩子;
(3)如果结点i有孩子,那么它的左孩子是2i,右孩子是2i+1。
代码实现:
class Heap{
static int max = 100000;
int size = 0;//用于记录元素个数
int[] array;
public Heap(){
array = new int[max];
}
/**
* 入堆
* @param x 要插入的元素
*/
public void push(int x){
array[++size] = x;
int i = size;//得到最后一个元素的下标
//自底向上调整
while (i > 1 && array[i] < array[i>>1]){
swap(array,i,i>>1);
i >>= 1;
}
}
/**
* 出堆
*/
public void pop(){
array[1] = array[size--];//将根节点赋值为最后一个节点,总数减一
int i = 1;//根节点
//自顶向下调整
while (2 * i <= size){//至少存在左子节点
int left = 2 * i;
if (left < size && array[left+1] < array[left])
//son<size表示有右子节点,选子节点中较小的
//右子节点更小
left ++;
if (array[left] < array[i]){//子节点较小,交换,否则已经满足最小堆结构直接退出
swap(array,left,i);
i = left;
}else break;
}
}
public void swap(int[] arr,int i,int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}