1.堆的概念和结构
1.1堆的概念
如果有一个关键词的集合K = {k0,k1,k2,…,kn-1},把它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中,并满足:Ki <= K2i+2 (Ki >= K2i+2) i = 0,1,2…则称为小堆(或大堆)。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。
1.2堆的性质
堆中某个节点的值总是大于或小于其父节点的值;
堆总是一棵完全二叉树。
1.3小根堆与大根堆
小跟堆: 完全二叉树 树中所有的父亲都是小于等于孩子
大跟堆: 完全二叉树 树中所有的父亲都是大于等于孩子
注意:不是从小到大存的,不一定是有序的。
逻辑结构是想象出来的,堆的逻辑结构是个二叉树
物理结构是数组
1.4堆的意义
堆排序
——O(N*logN)
topk
选出最大的前k个
1.5堆的实现
建堆的时间复杂度是O(N)
插入
原先是小堆 插入的值会影响祖先,需要向上调整 如果孩子比父亲小就交换两个的值,直到当父亲小于孩子
删除(
只删除堆顶元素,删除任意地方的值没有意义
)
直接使用挪动数据覆盖删除,树中的父子关系会被打乱删除堆顶的数据,继续保持删除后数据还是小堆
将堆顶与最后一个数据交换,删除最后一个 --size就可以了
开始向下调整
选出左右孩子中小的那一个,小的这个孩子跟父亲比较
如果比父亲小则交换,继续往下走
如果比父亲大则调整结束
1.5.1完整代码
Heap.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include<stdbool.h>
typedef int HPDataType;
typedef struct Heap
{
HPDataType* a;
int size;
int capacity;
}HP;
//交换位置
void Swap(HPDataType* p1, HPDataType* p2);
// O(logN)
void AdjustDwon(HPDataType* a, int size, int parent);
void AdjustUp(HPDataType* a, int child);
void HeapPrint(HP* php);
void HeapInit(HP* php);
void HeapDestroy(HP* php);
void HeapPush(HP* php, HPDataType x);
void HeapPop(HP* php);
HPDataType HeapTop(HP* php);
bool HeapEmpty(HP* php);
int HeapSize(HP* php);
Heap.c