堆的实现(优先队列)

结构定义

#include <iostream>
#include <algorithm>
using namespace std;
const int MaxV = 100;
const int MaxData = 1000;	//大于最大堆中所有元素可能的值

typedef struct HNode{
	int *Data;		//储存元素的数组
	int Size;		//堆中当前元素个数
	int Capacity;	//堆的最大容量
} * Heap;
typedef Heap MaxHeap;	//最大堆
typedef Heap MinHeap;	//最小堆

最大堆的初始化

/*创建最大容量为MaxSize的空的最大堆*/
MaxHeap CreateHeap(int MaxSize)
{
	MaxHeap H = new HNode;
	H->Data = new int[MaxSize + 1]();
	H->Size = 0;
	H->Capacity = MaxSize;
	H->Data[0] = MaxData;	//定义"哨兵"为大于堆中所有可能元素的值
	return H;
}

最大堆的插入

/*最大堆的插入
	1. 先将元素插入堆的末尾
	2. 从末尾元素开始向上遍历,如果x大于x的父节点,交换父子的值
	3. 直到x不大于x的父亲
*/
void InsertMaxHeap(MaxHeap H, int x)
{
	if(H->Size == H->Capacity)
		return;
	int i;
	for (i = ++H->Size; H->Data[i / 2] < x; i/=2)	//退出循坏条件是,x的父亲 >= x
		H->Data[i] = H->Data[i / 2];	//满足条件,进入循环交换元素(上滤x)
	H->Data[i] = x;		//类似于插入排序的交换
}

最大堆的删除

/*最大堆的删除
	1. 最大值为树根,取出最大值然后将堆末尾元素插入树根
	2. 调整堆,从作为调整的子树的根判断,选出最大的孩子与根比较
	3. 若孩子大于根,交换
	4. 以交换后的孩子作为新的调整的子树的根,重复2,3
	5. 若发现两个孩子都 <= 根,退出循环
*/
int DeleteMaxHeap(MaxHeap H)
{
	if(H->Size == 0)	//如果堆为空,返回MaxData表示删除失败
		return MaxData;
	int MaxItem = H->Data[1];
	int x = H->Data[H->Size--];	//需要插入的堆末尾元素
	int i, child;
	//如何确定循环次数? //最大循环次数是: 当以x为根的孩子是最后一个元素时,即 i*2 = H->Size
	for (i = 1; i * 2 <= H->Size ; i = child)	//i为父亲,父亲从上往下(下滤x)
	{
		child = i * 2;	//根的左孩子				//child != H->Size 是为了保证x有两个孩子
		if((H->Data[child] < H->Data[child + 1]) && child != H->Size)	//H->Size == child 则child + 1会数组溢出
			child++;			//孩子更新为最大孩子
		/*下面是比较*/
		if(x >= H->Data[child])
			break;
		else
			H->Data[i] = H->Data[child];	//注意是哪两个比较
	}
	H->Data[i] = x;
	return MaxItem;
}

最大堆的建立

/*最大堆的建立
	1. 由上述最大堆的删除可知,在一个排好序的堆中,改变根的值,然后下滤,能调整为堆
	2. 根据堆的子树也是堆的性质,从H->Size/2开始,向上遍历依次下滤
*/
void PercDown(MaxHeap H, int k)	//以下标为k进行类似堆的删除的下滤!!!
{
	int x = H->Data[k];
	int i, child;
	for (i = k; i * 2 <= H->Size; i = child)
	{
		child = i * 2;
		if((H->Data[child] < H->Data[child + 1]) && child != H->Size)
			child++;
		if(x >= H->Data[child])
			break;
		else
			H->Data[i] = H->Data[child];
	}
	H->Data[i] = x;
}

void BuildHeap(MaxHeap H)
{
	for (int i = H->Size / 2; i > 0; i--)
		PercDown(H, i);			//从H->Size/2开始向上
}
int main()
{
	MaxHeap H = CreateHeap(MaxV);
	int n;
	cin >> n;
	int *Array = new int[n];
	// for (int i = 0; i < n; i++)
	// {
	// 	cin >> Array[i];
	// 	InsertMaxHeap(H, Array[i]);
	// }
	for (int i = 1; i <= n; i++)
		cin >> H->Data[i];
	H->Size = n;
	BuildHeap(H);

	for (int i = 0; i <= n; i++)
		cout << H->Data[i] << " ";
	cout << endl;

	delete[] Array;
	delete[] H->Data;
	delete H;
	system("pause");
	return 0;
}
input:
10
10 26 56 98 48 74 12 32 65 22

output:
1000 98 65 74 32 48 56 12 10 26 22

堆排序常用于快速找最值,如Prim算法的找最小边

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值