heap.h
// 1. 堆是一个完全二叉树
// 2. 堆有两种, 一种叫小堆(小根堆, 最小堆),
// 一种叫大堆(大根堆, 最大堆).
// 3. 以小堆为例, 这个树的根节点是这个树中的最小的元素
// 对于任意一个子树来说, 子树的根节点, 小于左右孩子节点的值.
// 4. 以大堆为例, 这个树的根节点是这个树中的最大元素
// 对于任意一个子树来说, 子树的根节点, 大于左右孩子节点的值.
#pragma once
#include<stddef.h>
#define HeapMaxSize 1000
typedef char HeapType;
typedef int (*Compare)(HeapType a, HeapType b);
typedef struct Heap {
HeapType data[HeapMaxSize];
size_t size;
Compare cmp;
} Heap;
void HeapInit(Heap* heap, Compare compare);
void HeapInsert(Heap* heap, HeapType value);
// 取堆顶元素
int HeapRoot(Heap* heap, HeapType* value);
// 删除堆顶元素
void HeapErase(Heap* heap);
int HeapEmpty(Heap* heap);
size_t HeapSize(Heap* heap);
void HeapDestroy(Heap* heap);
// 在我们不想开辟额外的空间, 或者消耗额外的时间的前提下,
// 如果我们想进行从小到大排序, 就需要一个大堆
// 如果我们想进行从大到小排序, 就需要一个小堆
void HeapSort(HeapType array[], size_t size);
heap.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"heap.h"
#define HeapMaxSize 1000
#define TEST_HEADER printf("\n===============%s===============\n",__FUNCTION__)
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 compare)
{
if(heap==NULL)
{
return;
}
heap->size=0;
heap->cmp=compare;
}
void HeapDestroy(Heap* heap)
{
if(heap==NULL)
{
return;
}
heap->size=0;
heap->cmp=NULL;
}
void Swap_data(HeapType* a,HeapType* b)
{
HeapType tmp =*a;
*a=*b;
*b=tmp;
return;
}
void Adjustup(Heap* heap)
{
int child=heap->size-1;
int parent=(child-1)/2;
while(child>0)
{
if(!heap->cmp(heap->data[parent],heap->data[child]))
{
Swap_data(&heap->data[parent],&heap->data[child]);
}
else
{
return;
}
child=parent;
parent=(parent-1)/2;
}
}
void HeapInsert(Heap* heap, HeapType value)
{
if(heap==NULL)
{
return;
}
if(heap->size>=HeapMaxSize)
{
printf("The heap is full!");
return;
}
heap->data[heap->size++]=value;
Adjustup(heap);
}
// 取堆顶元素
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)
{
int parent=0;
int child=2*parent +1;
while(child < (int)heap->size)
{
if( child+1 < (int)heap->size)
{
if(!heap->cmp(heap->data[child],heap->data[child+1]))
{
++child;
}
}
if(!heap->cmp(heap->data[parent],heap->data[child]))
{
Swap_data(&heap->data[parent],&heap->data[child]);
}
else
{
return;
}
parent=child;
child=2*child+1;
}
}
// 删除堆顶元素
void HeapErase(Heap* heap)
{
if(heap==NULL)
{
return;
}
if(heap->size==0)
{
return;
}
if(heap->size==1)
{
--heap->size;
return;
}
Swap_data(&heap->data[0],&heap->data[heap->size-1]);
--heap->size;
Adjustdown(heap);
}
int HeapEmpty(Heap* heap)
{
if(heap==NULL)
{
return 0;
}
if(heap->size==0)
{
return 0;
}
return 1;
}
size_t HeapSize(Heap* heap)
{
if(heap==NULL)
{
return 0;
}
return heap->size;
}
void printall(Heap* heap)
{
int i=0;
for(i=0;i<6;i++)
{
printf("%c",heap->data[i]);
}
printf("\n");
}
void HeapPrint(Heap* heap,const char* str)
{
printf("\n----------%s---------\n",str);
int i=0;
printf("heap data:");
while(i < (int)heap->size)
{
printf("%c",heap->data[i]);
i++;
}
printf("\n");
printf("heap size:%lu\n",heap->size);
printf("heap cmp: Greater \n");
printf("\n");
printall(heap);
}
// 在我们不想开辟额外的空间, 或者消耗额外的时间的前提下,
// 如果我们想进行从小到大排序, 就需要一个大堆
// 如果我们想进行从大到小排序, 就需要一个小堆
void HeapSort(HeapType array[], size_t size)
{
Heap heap;
HeapInit(&heap,Greater);
size_t i=0;
while(i<size)
{
HeapInsert(&heap,array[i]);
i++;
}
HeapPrint(&heap,"Insert six value");
while(heap.size>0)
{
HeapErase(&heap);
}
HeapPrint(&heap,"Erease six value");
memmove(array,&heap.data,size);
}
void Testinit()
{
TEST_HEADER;
Heap heap;
HeapInit(&heap,Greater);
HeapPrint(&heap,"Init heap!");
}
void TestInsert()
{
TEST_HEADER;
Heap heap;
HeapInit(&heap,Greater);
HeapInsert(&heap,'e');
HeapInsert(&heap,'c');
HeapInsert(&heap,'d');
HeapInsert(&heap,'a');
HeapInsert(&heap,'f');
HeapInsert(&heap,'b');
HeapPrint(&heap,"insert heap");
}
void TestRoot()
{
TEST_HEADER;
Heap heap;
HeapType value;
HeapInit(&heap,Greater);
HeapInsert(&heap,'e');
HeapInsert(&heap,'c');
HeapInsert(&heap,'d');
HeapInsert(&heap,'a');
HeapInsert(&heap,'f');
HeapRoot(&heap,&value);
HeapPrint(&heap,"heap top expect f");
printf("value :%c \n",value);
}
void TestErease()
{
TEST_HEADER;
Heap heap;
HeapInit(&heap,Greater);
HeapInsert(&heap,'e');
HeapInsert(&heap,'c');
HeapInsert(&heap,'d');
HeapInsert(&heap,'a');
HeapInsert(&heap,'f');
HeapInsert(&heap,'b');
HeapPrint(&heap,"insert heap six value");
HeapErase(&heap);
HeapPrint(&heap,"Erease heap one value");
HeapErase(&heap);
HeapPrint(&heap,"Erease heap two value");
HeapErase(&heap);
HeapPrint(&heap,"Erease heap three value");
HeapErase(&heap);
HeapPrint(&heap,"Erease heap four value");
HeapErase(&heap);
HeapPrint(&heap,"Erease heap five value");
HeapErase(&heap);
HeapPrint(&heap,"Erease heap six value");
}
void TestHeapsort()
{
TEST_HEADER;
HeapType arr[]={'e','c','d','a','f','b'};
int size=sizeof(arr)/sizeof(arr[0]);
HeapSort(arr,size);
int i=0;
while(i<size)
{
printf("%c",arr[i]);
i++;
}
printf("\n");
}
int main()
{
Testinit();
TestInsert();
TestRoot();
TestErease();
TestHeapsort();
return 0;
}
运行结果
===============Testinit===============
----------Init heap!---------
heap data:
heap size:0
heap cmp: Greater
0<y�
===============TestInsert===============
----------insert heap---------
heap data:fedacb
heap size:6
heap cmp: Greater
fedacb
===============TestRoot===============
----------heap top expect f---------
heap data:fedac
heap size:5
heap cmp: Greater
fedacb
value :f
===============TestErease===============
----------insert heap six value---------
heap data:fedacb
heap size:6
heap cmp: Greater
fedacb
----------Erease heap one value---------
heap data:ecdab
heap size:5
heap cmp: Greater
ecdabf
----------Erease heap two value---------
heap data:dcba
heap size:4
heap cmp: Greater
dcbaef
----------Erease heap three value---------
heap data:cab
heap size:3
heap cmp: Greater
cabdef
----------Erease heap four value---------
heap data:ba
heap size:2
heap cmp: Greater
bacdef
----------Erease heap five value---------
heap data:a
heap size:1
heap cmp: Greater
abcdef
----------Erease heap six value---------
heap data:
heap size:0
heap cmp: Greater
abcdef
===============TestHeapsort===============
----------Insert six value---------
heap data:fedacb
heap size:6
heap cmp: Greater
fedacb
----------Erease six value---------
heap data:
heap size:0
heap cmp: Greater
abcdef
abcdef