数据结构-堆
1. 概述
堆,可以看作一棵完全二叉树,主要用于堆排序、优先级队列等。
堆分为大根堆和小根堆。
堆的性质:父节点的值大于(小于)其子节点的值。(对于大根堆为 大于, 小根堆为 小于);
2. 堆的基本术语
堆可以看作一棵完全二叉树,该树的高度为O(lgn).
A[n]表示堆的数组,下表从0开始,到n - 1结束;
*PARENT(i) :表示节点i的父节点,即 floor( (i - 1) / 2 );
*LEFT(i) : 表示节点i的左孩子,即2(i+1) - 1;
*RIGHT(i) : 表示节点i的右孩子,即2(i+1);
3. 基本操作
操作堆时,如果有修改,需要保持堆的基本性质。
下面以小根堆为例。
3.1 调整 Heapify(a, n, i)
// 思路:LEFT(i) 和 RIGHT(i) 都是堆,调整 PARENT(i)为根的子树为堆。
#define PARENT(i) ((i-1) / 2)
#define LEFT(i) (2(i+1) - 1)
#define RIGHT(i) (2(i+1))
void Heapify(int a[], int n, int i) {
int temp;
int left = LEFT(i);
int right = RIGHT(i);
int min = i;
if( left < n && a[min] > a[left] ) {
min = left;
}
if( right < n && a[min] > a[right] ) {
min = right;
}
if(min != i) {
temp = a[i];
a[i] = a[min];
a[min] = temp;
heapify(a, n, min);
}
}
3.2 建堆 BuildHeap(a, n)
// 把数组a[n]转化为小根堆。
void BuildHeap(int a[], int n) {
int i;
for(i = n / 2; i >= 0; i--) {
Heapify(a, n, i);
}
}
3.3 获取小根堆的最小值 GetMin(a[], int n)
// a[n]已经是最小堆,所以第一个元素即为最小值
int GetMin(int a[], int n) {
assert(a != NULL && n >= 0);
return a[0];
}
3.4 删除小根堆的根(即最小值), 并调整数组a仍然为小根堆;
int DelMin(int a[], int n) {
int min = a[0];
a[0] = a[n - 1];
n--;
Heapify(a, n, 0);
}
3.5 插入新数据 InsertHeap(int a[], n, val);
// 前提: a[n]处内存可用
void InsertHeap(int a[], int n, int val) {
int i = n;
a[n] = val;
n++;
while( i >= 0 && a[ PARENT(i) ] > a[i] ) {
a[i] = a[ PARENT(i) ];
i = PARENT(i);
}
a[i] = val;
}
4. Heap 排序
// descending order
void HeapSort(int a[], int n) {
int i;
int temp;
BuildHeap(a, n);
for(int i = n - 1; i > 0; i--) {
temp = a[0];
a[0] = a[i];
a[i] = temp;
Heapify(a, i, 0);
}
}

浙公网安备 33010602011771号