堆
堆:将数据按完全二叉树的顺序存储方式存储在一维数组
数组中的数据值同时满足 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;
}
住进火焰就成为萤火虫。
浙公网安备 33010602011771号