堆分为最大堆和最小堆, 堆一种特别的树…用数组表示的树
最大(小)堆的定义:
- 每个节点,最多有俩个子节点
- 根节点是最大(小)的, 且每个节点都比它的子节点要大(小)
- 除了根节点和最后一个节点可以没有兄弟节点, 其它节点都有兄弟节点
// 下标从0 开始 个数从1开始…
规律:下标为i, 它的左节点为2i+1 它的右节点为2i+2
下标为i的子节点, 它的父节点为 i/2-1
个数为 i 的子节点, 它的父节点为 (i-1)/ 2
堆一共有如下几种操作:初始化堆, 建堆, 向下调整, 插入, 向上调整,堆顶元素出队
#include <stdio.h>
#include <Windows.h>
#define DEFAULT_CAPACITY 128 //默认堆的大小
typedef struct _Heap{
int* arr; //堆的首地址
int size; //元素大小数量
int capacity; //对的空间容量
}Heap;
// 函数定义
bool initHeap(Heap* h, int* original, int size);
static void buildHeap(Heap* h);
static void adjustDown(Heap* h, int index);
// 初始化堆
bool initHeap(Heap* h, int* original, int size) {
if(!h || !original) return false;
int capacity = DEFAULT_CAPACITY > size ? DEFAULT_CAPACITY : size;
h->arr = new int[capacity];
if(!h->arr) return false;
h->capacity = capacity;
h->size = size;
if(size > 0) {
memcpy(h->arr, original, size* sizeof(int)) ;
h->size = size;
// 建堆
buildHeap(h);
} else {
h->size = 0;
}
return true;
}
// 建堆
void buildHeap(Heap* h) {
for(int i = h->size/2-1; i >=0; i--) {
// 向下调整
adjustDown(h, i);
}
}
// 向下调整
void adjustDown(Heap* h, int index) {
int cur = h->arr[index]; // 这次调整的数值
int parent, child; // 父和子
for(parent = index; parent*2+1 < h->size; parent = child) {
child = parent*2+1; //父节点的左子节点
//判断是否存在右子节点,并选出较大者
if(child+1 < h->size && h->arr[child] < h->arr[child+1]) {
child++;
}
//判断子节点和父节点的情况
if(cur > h->arr[child]) {
return; // 不需要调整
} else {
h->arr[parent] = h->arr[child];
h->arr[child] = cur;
}
}
}
// 向上调整
void adjustUp(Heap* h, int index) {
if(!h || !h->arr) return;
int temp = h->arr[index]; //保存要调整的值
int parent = (index-1)/2;
while(index >0 ) {
//判断调整的值, 和它的根节点情况
if(index >= 0) {
if(temp > h->arr[parent]) {
h->arr[index] = h->arr[parent];
h->arr[parent] = temp;
} else {
break;
}
} else {
break;
}
index = parent;
}
}
// 堆的插入
bool insert(Heap* h, int value) {
if(!h) return false;
if(h->size == h->capacity) return false;
int index = h->size;
h->arr[h->size] = value;
h->size++;
//向上调整
adjustUp(h, index);
}
// 堆顶元素出队
void DeHeap(Heap* h) {
if(!h || !h->arr) return;
h->arr[0] = h->arr[h->size-1];
h->size--;
// 向下调整
adjustDown(h, 0);
}
int main(void) {
Heap p;
int a[10] = {1,2,6,10,15,4,20,13,5,8};
// 初始化堆
initHeap(&p, a, 10);
for(int i=0; i<10; i++) {
printf("%d ", p.arr[i]);
}
printf("\n");
DeHeap(&p);
system("pause");
return 0;
}
测试图: