堆是一个完全二叉树,堆分两种,一种为小堆,一种为大堆 小堆是指对于这个树的任意任意一个子树来说,子树的根节点都要小于左右孩子节点的值,小堆的根节点是这个树的最小元素,每条路径上的节点都是递增的 大堆是指对于这个树的任意任意一个子树来说,子树的根节点都要大于左右孩子节点的值,大堆的根节点是这个树的最大元素,每条路径上的节点都是递减的 堆的结构定义如下: 其中compare函数用来缺点创建的是大堆还是小堆,Greater选择创建大堆,Less选择创建小堆
#pragma once typedef int HPDataType; typedef int(*PCOM) (HPDataType, HPDataType); int Less(HPDataType left, HPDataType right); int Greater(HPDataType left, HPDataType right); typedef struct Heap { HPDataType * _array; HPDataType _capacity; HPDataType _size; PCOM compare; }Heap; void InitHeap(Heap* hp, HPDataType* array, int size, PCOM compare); void InitEmptyHeap(Heap* hp, int capacity, PCOM compare); void InsertHeap(Heap* hp, HPDataType data); void EraseHeap(Heap* hp); int HeapSize(Heap* hp); int HeapEmpty(Heap* hp); HPDataType HeapTop(Heap* hp); void DestroyHeap(Heap* hp);堆的初始化
void AdjustDown(Heap* hp, size_t index) { assert(hp); size_t parent = index; size_t child = 2 * index + 1; while (child < hp->_size) { if ((child + 1 < hp->_size) && hp->compare(hp->_array[child] ,hp->_array[child + 1])) { child = child + 1; //判断左子树合适还是右子树合适; } if (hp->compare(hp->_array[parent] , hp->_array[child])) { swap(&hp->_array[parent], &hp->_array[child]); } parent = child; child = 2 * parent + 1; } } void InitHeap(Heap* hp, HPDataType* array, int size,PCOM compare) { assert(hp); HPDataType* _arr = (HPDataType*)malloc(sizeof(HPDataType)*size); if (_arr == NULL) { assert(0); return NULL; } hp->_array = _arr; for (int i = 0; i<size; ++i) { hp->_array[i] = array[i]; } hp->_capacity = size; hp->_size = size; hp->compare = compare; } //创建一个堆结构 void CreatHeap(Heap* hp) { assert(hp); for (int dep = (hp->_size - 1) / 2; dep >= 0; --dep) { AdjustDown(hp, dep); } }查看堆顶元素,查看堆成员个数等操作
//取堆顶元素 HPDataType HeapTop(Heap* hp) { assert(hp); if (hp->_size == 0) { return; } return hp->_array[0]; } //删除堆顶操作操作 void EraseHeap(Heap *hp) { assert(hp); if (hp->_size == 0) { return NULL; } swap(&hp->_array[0], &hp->_array[hp->_size - 1]); hp->_size--; AdjustDown(hp, 0); } int HeapSize(Heap* hp) { assert(hp); return hp->_size; } int HeapEmpty(Heap* hp) { assert(hp); if (!hp->_size) { return 1; } return 0; } HPDataType Head_Is_Full(Heap* hp) { assert(hp); if (hp->_capacity == hp->_size) { return 1; } return 0; } //在堆中插入值为Data的元素 void InsertHeap(Heap* hp, HPDataType data) { assert(hp); //容量不够,进行扩容 if (Head_Is_Full) { int newcapacity = hp->_capacity * 2; HPDataType * newarr = (HPDataType *)malloc(sizeof(HPDataType) * newcapacity); if (newarr == NULL) { assert(0); return NULL; } for (int i = 0; i < hp->_size; ++i) { newarr[i] = hp->_array[i]; } hp->_array = newarr; hp->_capacity = newcapacity; } hp->_array[hp->_size] = data; CreatHeap(hp); hp->_size++; } void DestroyHeap(Heap* hp) { assert(hp); free(hp->_array); hp->_capacity = 0; hp->_size = 0; }实现堆排序,解决TOP k问题 Greater为升序排列 Less为降序排列
void SortHeap(HPDataType *_arr, size_t size) { Heap hp; InitHeap(&hp, _arr, size,Greater); CreatHeap(&hp); for (int i = 0; i < size; ++i) { EraseHeap(&hp); } hp._size = size; //升序取前5个数 for (int i = size-1; i >= 0; --i) { printf("%d ", hp._array[i]); } DestroyHeap(&hp); } int main() { int _arr[] = { 8,7,6,5,1,3,6,8,9,0,2,11,15,17,19 }; int size = sizeof(_arr) / sizeof(_arr[0]); SortHeap(_arr, size); system("pause"); return 0; }