一、简介
- 是一种树状的数据结构
- 常见的堆有:
1. 二叉堆(完全二叉堆,其逻辑结构就是一棵完全二叉树)
2. 多叉堆
3. 索引堆
4. 二项堆
5. 斐波那契堆
6. 左斜堆 - 性质
1. 任意节点的值总是 >= 或 <= 子节点的值
2. 如果任意结点的值 >= 子节点的值,则称为大根堆或最大堆
3. 如果任意结点的值 <= 子节点的值,则成为小根堆或最小堆
4. 上一层的值不一定全都大于下一层的值。
二、二叉堆(数组存放,最大堆为例)
- 如果 i=0 ,则为根结点
- i > 0,父结点索引为(i-1)/2,向下取整
- 如果 2i+1 <= n-1,他的左子节点索引为 2i+1
- 如果 2i+1 > n-1,则无左子节点
- 如果 2i+2 <= n-1,他的右子节点索引为 2i+2
- 如果 2i+2 > n-1,则无右子节点
- 插入操作 O(logn):直接插入到数组的最后,然后执行上滤操作,即跟父结点比较,如果比父节点大则交换位置
public static void shiftUp(int[] nums,int index){
int temp=nums[index];
while(index > 0){
int parentIndex = (index-1)>>1;
if(temp <= nums[parentIndex]){
break;
}
nums[index] = nums[parentIndex];
index = parentIndex;
}
nums[index]=temp;
}
- 删除操作 O(logn):堆中的删除是指删除根结点,具体步骤为用堆中最后一个元素覆盖根元素,然后执行下滤操作,即将当前结点与子结点进行比较,如果 >= 子结点或者无子结点则不做任何操作,如果小于子节点,则与子节点中大的那个子结点交换位置。
public static void shiftDown(int[] nums,int index){
int half=(nums.length)>>1;
int temp=nums[index];
while(index < half){
int childIndex=(index<<1)+1;
int child=nums[childIndex];
int rightIndex=childIndex+1;
if(rightIndex<nums.length && nums[rightIndex]>child){
child=nums[childIndex=rightIndex];
}
if(temp >= nums[childIndex]) {
break;
}
nums[index] = child;
index=childIndex;
}
nums[index]=temp;
}
- 原地建堆(给出一个数组使其变为堆)
有两种方法:
- 自上而下的上滤
- 自下而上的下滤
public class Heap {
public static void main(String[] args) {
int[] nums=new int[5];
nums[0] = 0;
nums[1] = 1;
nums[2] = 2;
nums[3] = 3;
nums[4] = 4;
for(int i=(nums.length>>1)-1; i >= 0; i--) {
shiftDown(nums, i);
}
for(int i=1; i < nums.length; i++) {
shiftUp(nums, i);
}
}
public static void shiftUp(int[] nums,int index){
int temp=nums[index];
while(index > 0){
int parentIndex = (index-1)>>1;
if(temp <= nums[parentIndex]){
break;
}
nums[index] = nums[parentIndex];
index = parentIndex;
}
nums[index]=temp;
}
public static void shiftDown(int[] nums,int index){
int half=(nums.length)>>1;
int temp=nums[index];
while(index < half){
int childIndex=(index<<1)+1;
int child=nums[childIndex];
int rightIndex=childIndex+1;
if(rightIndex<nums.length && nums[rightIndex]>child){
child=nums[childIndex=rightIndex];
}
if(temp >= nums[childIndex]) {
break;
}
nums[index] = child;
index=childIndex;
}
nums[index]=temp;
}
}