#include <stdio.h>
#include <stdlib.h>
typedef int E;
//定义一个数组用来存放堆
typedef struct Heap{
E *array;
int capacity;
int size;
} *Heap;
Heap createHeap(int capacity){
Heap heap = (Heap)malloc(sizeof(struct Heap));
heap->array = (E *)malloc(capacity * sizeof(E));
heap->capacity = capacity;
heap->size = 0;
return heap;
}
Heap insert(Heap heap, E element){
if (heap->size == 0){ //如果size==0说明heap为空,直接将heap的第一个元素变成要插入的元素即可
heap->array[0] = element;
}else{
if (heap->size + 1 > heap->capacity){ //先判断size+1如果大于容量,说明再进行插入就要溢出了,就将数组扩个容
int newcapacity = heap->capacity * 2;
E *newarray = realloc(heap->array, newcapacity * sizeof(E));
if (newarray == NULL) printf("error of realloc");
heap->array = newarray;
heap->capacity = newcapacity;
}
int index = heap->size; //heap的size也就是最大下标加一,先将队尾加入要加入的元素,然后再进行上浮
heap->array[index] = element;
while (heap->array[(index - 2) / 2] > element && index != 0){ //(index-2)/2可以用来找到父元素,1判断父元素是否比自身大;2判断自身是否还不是根节点了。满足这两条件才能上浮
E temp = heap->array[(index - 2) / 2];
heap->array[(index - 2) / 2] = element; //这几步是进行交换
heap->array[index] = temp;
index = (index - 2) / 2; //交换完之后将index更新迭代
}
}
heap->size ++; //插入完成后size加一
return heap;
}
int minIndex(Heap heap, int ind1, int ind2){ //写一个函数输入一个heap和两个下标,判断两下标对应的元素哪个更小,然后返回这个元素的下标
return (heap->array[ind1] < heap->array[ind2]) ? ind1 : ind2;
}
E pop(Heap heap){
if (heap->size == 0) return 0; //如果size==0,说明heap为空则返回0吧
E begin = heap->array[0]; //保留begin,其实如果看做树的话说是root也更合适
E end = heap->array[heap->size - 1];
heap->array[0] = end; //直接将末尾的节点拿过来,做一次下浮
E index = 0; //同理index * 2 + 1,index * 2 + 2分别代表左节点和右节点
while(heap->array[index] > heap->array[minIndex(heap, index * 2 + 1, index * 2 + 2)] && minIndex(heap, index * 2 + 1, index * 2 + 2) <= heap->size - 1){
E exchange = minIndex(heap, index * 2 + 1, index * 2 + 2); //1先找到左节点和右节点哪个更小,因为我们需要下浮的元素当然最好是和更小的元素比较
E temp = heap->array[exchange]; //2满足条件如下:
heap->array[exchange] = heap->array[index]; //(a)下浮元素比下一层的元素还小
heap->array[index] = temp; //(b)要做下浮交换的节点不能是未定义的,判断是否未定义就看要退换元素是否超过索引最大值
index = exchange; //3交换完之后将index更新迭代
}
heap->size--;
return begin; //别忘了返回一开始的根节点
}
void printHeap(Heap heap){
for (int i = 0; i < heap->size; i++){
printf("%d ", heap->array[i]);
}
printf("\n");
}
int main(){
Heap heap = createHeap(10);
for (int i = 1; i < 21; i++){
heap = insert(heap, i);
}
printHeap(heap);
for (E i = 1; i < 21; i++){
pop(heap);
printHeap(heap);
}
return 1;
}
// 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
// 2 4 3 8 5 6 7 16 9 10 11 12 13 14 15 20 17 18 19
// 3 4 6 8 5 12 7 16 9 10 11 19 13 14 15 20 17 18
// 4 5 6 8 10 12 7 16 9 18 11 19 13 14 15 20 17
// 5 8 6 9 10 12 7 16 17 18 11 19 13 14 15 20
// 6 8 7 9 10 12 14 16 17 18 11 19 13 20 15
// 7 8 12 9 10 13 14 16 17 18 11 19 15 20
// 8 9 12 16 10 13 14 20 17 18 11 19 15
// 9 10 12 16 11 13 14 20 17 18 15 19
// 10 11 12 16 15 13 14 20 17 18 19
// 11 15 12 16 18 13 14 20 17 19
// 12 15 13 16 18 19 14 20 17
// 13 15 14 16 18 19 17 20
// 14 15 17 16 18 19 20
// 15 16 17 20 18 19
// 16 18 17 20 19
// 17 18 19 20
// 18 20 19
// 19 20
// 20
堆(优先级队列)实现
最新推荐文章于 2024-05-23 20:47:46 发布