- 堆(heap)也被称为优先队列(priority queue)。队列中允许的操作是先进先出(FIFO),在队尾插入元素,在队头取出元素。而堆也是一样,在堆底插入元素,在堆顶取出元素,但是堆中元素的排列不是按照到来的先后顺序,而是按照一定的优先顺序排列的。这个优先顺序可以是元素的大小或者其他规则。
- 堆可以分为最大堆和最小堆。
最大堆满足:(1)根节点为最大值;(2)父节点大于子节点。
堆最小堆满足:(1)根节点为最小值;(2)父节点小于子节点。
- 堆的基本操作:(1)取堆顶元素;(2)删除堆顶元素;(3)插入一个元素。
- 堆的代码实现:
heap.h:
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stddef.h>
#define HeapMaxSize 1024
typedef char HeapType;
typedef int(*Compare)(HeapType a,HeapType b);
typedef struct Heap{
HeapType data[HeapMaxSize];
size_t size;
Compare cmp;
}Heap;
int Greater(HeapType a, HeapType b);
int Less(HeapType a,HeapType b);
void HeapInit(Heap* heap,Compare cmp);
void HeapDestroy(Heap* heap);
void HeapInsert(Heap* heap,HeapType value);
void AdjustUp(Heap* heap,size_t index);
void Swap(HeapType* a,HeapType* b);
void HeapPrintChar(Heap* heap,const char* msg);
int HeapRoot(Heap* heap,HeapType* value);
void HeapErase(Heap* heap);
void AdjustDown(Heap* heap,size_t index);
void HeapCreate(Heap* heap,HeapType array[],size_t size);
void HeapSort(HeapType array[],size_t size);
heap.c:
#include "heap.h"
int Greater(HeapType a,HeapType b){
return a>b?1:0;
}
int Less(HeapType a,HeapType b){
return a<b?1:0;
}
void HeapInit(Heap* heap,Compare cmp){
//初始化时决定这个堆是大堆还是小堆
heap->size = 0;
heap->cmp = cmp;
return;
}
void HeapDestroy(Heap* heap){
heap->size = 0;
heap->cmp = NULL;
return;
}
void Swap(HeapType* a,HeapType* b){
HeapType tmp = *a;
*a = *b;
*b = tmp;
return;
}
void AdjustUp(Heap* heap,size_t index){
if(heap == NULL)
return;
size_t child = index;
size_t parent = (child-1)/2;
while(child > 0){
if(!heap->cmp(heap->data[parent],heap->data[child])){
Swap(&heap->data[parent],&heap->data[child]);
}
else{
break;
}
child = parent;
parent = (child-1)/2;
}
return;
}
void HeapInsert(Heap* heap,HeapType value){
if(heap == NULL)
return;
if(heap->size >= HeapMaxSize)
return;
heap->data[heap->size++] = value;
AdjustUp(heap,heap->size-1);
return;
}
void HeapPrintChar(Heap* heap,const char* msg){
printf("[%s]\n",msg);
size_t i = 0;
for(;i < heap->size;i++){
printf("[%c | %lu] ",heap->data[i],i);
}
printf("\n");
}
int HeapRoot(Heap* heap,HeapType* value){
if(heap == NULL)
return 0;
if(heap->size == 0)
return 0;
*value = heap->data[0];
return 1;
}
void AdjustDown(Heap* heap,size_t index){
if(heap == NULL)
return;
size_t parent = index;
size_t child = 2*index+1;
while(child < heap->size){
if(child+1 < heap->size && heap->cmp(heap->data[child+1],heap->data[child])){
child = child+1;
}
if(heap->cmp(heap->data[child],heap->data[parent])){
Swap(&heap->data[child],&heap->data[parent]);
}
else{
break;
}
parent = child;
child = 2*parent+1;
}
}
void HeapErase(Heap* heap){
if(heap == NULL)
return;
if(heap->size == 0)
return;
Swap(&heap->data[0],&heap->data[heap->size-1]);
--heap->size;
AdjustDown(heap,0);
}
void HeapCreate(Heap* heap,HeapType array[],size_t size){
if(heap == NULL)
return;
size_t i = 0;
for(;i < size; i++){
HeapInsert(heap,array[i]);
}
return;
}
void HeapSort(HeapType array[],size_t size){
Heap heap;
HeapInit(&heap,Greater);
HeapCreate(&heap,array,size);
while(heap.size > 0){
HeapErase(&heap);
}
memcpy(array,heap.data,size*sizeof(HeapType));
return;
}
test.c:
#include"heap.h"
#define PRINT_HEAD printf("\n============%s============\n",__FUNCTION__);
extern Greater(HeapType a,HeapType b);
void TestInit(){
PRINT_HEAD;
Heap heap;
HeapInit(&heap,Greater);
printf("size expect 0,actual %lu\n",heap.size);
}
void TestInsert(){
PRINT_HEAD;
Heap heap;
HeapInit(&heap,Greater);
HeapInsert(&heap,'a');
HeapInsert(&heap,'d');
HeapInsert(&heap,'c');
HeapInsert(&heap,'b');
HeapInsert(&heap,'f');
HeapInsert(&heap,'e');
HeapPrintChar(&heap,"插入六个元素");
HeapDestroy(&heap);
printf("size expect 0,actual %lu\n",heap.size);
}
void TestRoot(){
PRINT_HEAD;
Heap heap;
HeapInit(&heap,Greater);
HeapInsert(&heap,'a');
HeapInsert(&heap,'d');
HeapInsert(&heap,'c');
HeapInsert(&heap,'b');
HeapInsert(&heap,'f');
HeapInsert(&heap,'e');
HeapType value = 0;
int ret = HeapRoot(&heap,&value);
printf("ret expect 1,actual %d\n",ret);
printf("value expect f,actual %c\n",value);
}
void TestErase(){
PRINT_HEAD;
Heap heap;
HeapInit(&heap,Greater);
HeapInsert(&heap,'a');
HeapInsert(&heap,'d');
HeapInsert(&heap,'c');
HeapInsert(&heap,'b');
HeapInsert(&heap,'f');
HeapInsert(&heap,'e');
HeapPrintChar(&heap,"插入六个元素");
HeapErase(&heap);
HeapPrintChar(&heap,"删除一个元素");
}
void TestCreate(){
PRINT_HEAD;
Heap heap;
HeapInit(&heap,Greater);
HeapType array[] = {'a','d','c','b','f','e'};
size_t size = sizeof(array)/sizeof(array[0]);
HeapCreate(&heap,array,size);
HeapPrintChar(&heap,"创建堆");
}
void TestSort(){
Heap heap;
HeapType array[] = {'a','d','c','b','f','e'};
size_t size = sizeof(array)/sizeof(array[0]);
HeapSort(array,size);
HeapPrintChar(&heap,"堆排序");
}
int main(){
TestInit();
TestInsert();
TestRoot();
TestErase();
TestCreate();
TestSort();
return 0;
}
结果演示: