数据结构-堆

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);
	}
}
posted @ 2016-10-24 14:24  mizhouli  阅读(110)  评论(0)    收藏  举报