堆的简单实现及其应用

/* *
 * 	堆的特性
 *
 *	1. 堆是一颗二叉树
 *	2. 堆的每个节点都比它的子节点要大
 *
 * 	堆的常见应用
 *
 * 	1. 堆排序
 * 	2. 优先队列
 *
 * */

/* *
 *	下面是一个堆的普通实现
 * */

class Heap {
/* *
 *	这里用数组来表示一个堆, 
 *	+-+-+-+-+-+-+-+
 *      |0|1|2|3|4|5|6|
 *	+-+-+-+-+-+-+-+
 * */
	int *data;
	int maxSize;
	int size;
public:
	Heap();
	Heap(int n);
	~Heap();
/* *
 *	从数组中自底向上用下沉操作构建堆
 * */
	static Heap* Build(int *array, int n);
/* *
 *	数组尾部插入一个元素, size加1, 然后沿着根节点路径上浮
 * */
	void Push(int val);
/* *
 *	交换数组末尾的节点和根节点, size减1, 对新的根节点执行下沉操作
 * */
	void Pop();
/* *
 *	节点i沿着到达根节点的路径一直冒泡(比较并交换), 直到到达根节点或者
 *	遇到比它大的节点时结束
 * */
	void ToUp(int i);
/* *
 *	节点i沿着较大的子节点向下沉, 
 *	直到叶子节点或者两个子节点都比他小时结束
 * */
	void ToDown(int i);
/* *
 *	获得堆顶元素
 * */
	int &Top();
/* *
 *	判断堆是否为空
 * */
	bool Empty();
private:
/* *
 *	节点i的左节点在数组中的下标是2*i + 1
 */
	int Left(int i);
/* *
 *	节点i的左节点在数组中的下标是2*i + 2
 * */
	int Right(int i);
/* *
 *	节点i的父节点在数组中的下标是(i - 1) / 2
 * */
	int Parent(int i);
/* *
 *	二叉树中非叶子节点的个数是size / 2
 * */
	int NotLeaf();
/* *
 *	交换数组中下标为i和j的节点内容
 * */
	void Swap(int i, int j);
/* *
 *	比较数组中下标为i和j的节点内容的大小
 * */
	bool Compare(int i, int j);
};

int Heap::Left(int i) {
	return (i << 1) + 1;
}

int Heap::Right(int i) {
	return (i << 1) + 2;
}

int Heap::Parent(int i) {
	return i - 1 >> 1;
}

void Heap::Swap(int i, int j) {
	int tmp = data[i];
	data[i] = data[j];
	data[j] = tmp;
}

bool Heap::Compare(int i, int j) {
	return data[i] >= data[j];
}

int Heap::NotLeaf() {
	return size >> 1;
}

void Heap::ToUp(int i) {
	while(i && Compare(i, Parent(i))) {
		Swap(i, Parent(i));
		i = Parent(i);
	}
}

void Heap::ToDown(int i) {
	while(i < NotLeaf()) {
		if(Right(i) >= size || Compare(Left(i), Right(i))) {
			if(!Compare(Left(i), i))
				break;
			Swap(Left(i), i);
			i = Left(i);
			continue;
		}
		if(!Compare(Right(i), i))
			break;
		Swap(Right(i), i);
		i = Right(i);
	}
}

Heap* Heap::Build(int *array, int n) {
	Heap *heap = new Heap();
	heap -> data = new int[n + 1];
	heap -> maxSize = n;
	heap -> size = n;
	for(int i=0;i<n;++i)
		heap -> data[i] = array[i];
	for(int i=heap->NotLeaf()-1;i>=0;--i)
		heap->ToDown(i);
	return heap;
}

Heap::Heap() : data(0), size(0), maxSize(0) {}

Heap::Heap(int n) : data(new int[n + 1]), size(0), maxSize(n) {}

Heap::~Heap() {
	delete []data;
}

void Heap::Push(int val) {
	data[size++] = val;
	ToUp(size - 1);
}

void Heap::Pop() {
	Swap(0, --size);
	ToDown(0);
}

int &Heap::Top() {
	return data[0];
}

bool Heap::Empty() {
	return 0 == size;
}

void HeapSort(int a[], int n) {
	Heap *heap = Heap::Build(a, n);
	while(!heap -> Empty()) {
		a[--n] = heap -> Top();
		heap -> Pop();
	}
	delete heap;
}

void TopK(int src[], int n, int dst[], int k) {
	Heap *heap = Heap::Build(src, k);
	for(int i=k;i<n;++i)
		if(src[i] <= heap -> Top()) {
			heap -> Top() = src[i];
			heap -> ToDown(0);	
		}
	
	while(!heap -> Empty()) {
		dst[--k] = heap -> Top();
		heap -> Pop();
	}

	delete heap;
}

#include "stdio.h"

int main() {
	int a[] = {3, 1, 2, 4 ,5, 7, 5, 2, 9, 3};
	int n = sizeof(a) / sizeof(int);
	int b[5];
	
	TopK(a, n, b, 5);
	for(int i=0;i<5;++i)
		printf("%d ", b[i]);
	printf("\n");
	
	HeapSort(a, n);
	for(int i=0;i<n;++i)
		printf("%d ", a[i]);
	printf("\n");

	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值