堆:将数据按完全二叉树的顺序存储方式存储在一维数组
数组中的数据值同时满足 a[i]>=2a[i]+1 和 a[i]>=2a[i]+2
或者同时满足a[i]<=2a[i]+1 和 a[i]<=2a[i]-1
堆的特性:是完全二叉树
大堆,每个双亲节点的值总是大于(等于)子节点的值。
小堆,每个双亲节点的值总是小于(等于)子节点的值。
数据结构中的堆和内存中的堆的区别:
数据结构中的堆是一种数据的存储结构,是算法,而内存堆区是内存中区别于栈区、静态常量区的一个数据存储区域。
创建堆:讲数组(序列)在逻辑上看成完全二叉树,然后通过算法从倒数第一个非叶子节点进行调整,最后得到堆。
插入元素时:将元素插入到数组的尾上,然后将其与父节点对比向上调整。
删除:将顶元素与最后一个元素交换,再进行调整,最后将记录元素个数的那个值减1
堆排序:有两种,1 将数组放到堆中,一次取堆顶元素放回数组,并删除对顶元素 (额外开辟空间)
2 将数组放到堆中,调整完后形成需要的堆,然后依次取堆顶元素 (不开辟空间,浪费时间)
TOPk问题,取前面的几个数据建小堆,后面的数据和堆中的数据对比,大于堆顶则替换堆顶元素,然后向下调整
typedef int DataType;
typedef struct Heap
{
int *arr;
int capacity;
int size;
}Heap;
// 销毁堆 void DestroyHeap(Heap* heap) { if (heap == NULL) { return; } //capacity和数组可以不用再管 heap->size = 0; return; } // 获取堆中有效元素个数 int SizeHeap(Heap* heap) { if (heap == NULL) { return 0; } return heap->size; } // 检测堆是否为空 int EmptyHeap(Heap* heap) { if (heap == NULL) { return 0; } return heap->size == 0 ? 1 : 0; } //堆化 void heapify(int a[], int size, int index) { // index 是不是叶子结点? index 有没有孩子? // index 有没有左孩子? index 左孩子下标是否越界? if (2 * index + 1 >= size) { return; } int min = 2 * index + 1; if (2 * index + 2 < size && a[2 * index + 2] < a[2 * index + 1]) { min = 2 * index + 2; } if (a[index] <= a[min]) { return; } int t = a[min]; a[min] = a[index]; a[index] = t; heapify(a, size, min); } void HeapInit(Heap *heap, int a[], int size) { for (int i = 0; i < size; i++) { heap->arr[i] = a[i]; } heap->size = size; createHeap(heap->arr, heap->size); } void adjustUp(int a[], int index) { while (index > 0) { if (index == 0) { return; } int parent = (index - 1) / 2; if (a[parent] <= a[index]) { return; } int t = a[parent]; a[parent] = a[index]; a[index] = t; index = parent; } } void HeapPush(Heap *heap, int val) { heap->arr[heap->size++] = val; adjustUp(heap->arr, heap->size - 1); } void HeapPop(Heap *heap) { assert(heap->size > 0); heap->arr[0] = heap->arr[heap->size - 1]; heap->size--; heapify(heap->arr, heap->size, 0); } void createHeap(int arr[], int size) { //(size-2)/2 划分开始的界限,从最后一个非叶节点 for (int i = (size - 2) / 2; i >= 0; i--) { int index = i; while (1) { int left = 2 * index + 1; int right = 2 * index + 2; if (left >= size) { return; } int min = left; if (right < size && arr[right] < arr[left]) { min = right; } if (arr[index] <= arr[min]) { return; } int t = arr[min]; arr[min] = arr[index]; arr[index] = t; index = min; } } } int main() { int arr[10] = { 5, 2, 6, 9, 8, 3, 0, 4, 1, 7 }; int size = sizeof(arr) / sizeof(arr[0]); //Heap* createHeap(arr, size); return 0; }