最大优先队列

 堆排序是一种集插入排序和选择排序的有点于一身的排序算法,但是在后面能学习到更加好的快速排序算法,性能优于堆排序。堆这钟数据结构还有许多其他的用处,例如作为高效的优先队列。优先队列分为最大优先队列和最小优先队列,今天学习了如何用最大堆来实现最大优先队列。

    优先队列是一种用来维护由一组元素构成的集合S的数据结构,其中的每一个元素都有一个相关的值,称为关键字。一个最大优先队列应该支持下面的四种操作:

  1. MAXIMUM(S):将集合S中的最大关键字的元素返回。
  2. EXTRACT_MAX(S):返回并去掉S中最大的元素。
  3. INCREASE_KEY(S,x,k):将集合S中的x元素关键字的值提升至k,假设k不小于原x的关键字值。
  4. INSERT(S,x):将元素x插入集合S中。
#include<stdio.h>
#include<stdlib.h>

//针对节点i及其子树进行最大堆的调整
void max_heapify(int* a, int i, int count)   //a是需要构造最大堆的数,count为数的个数
{
	int left_index, right_index;
	int max_index = i;
	left_index = 2 * i + 1;
	right_index = left_index + 1;
	if ((left_index <= count) && (a[left_index] > a[max_index]))
		max_index = left_index;
	if ((right_index <= count) && (a[right_index] > a[max_index]))
		max_index = right_index;
	if (max_index != i)
	{
		int t = a[i];
		a[i] = a[max_index];
		a[max_index] = t;
		max_heapify(a, max_index, count);
	}
}

//建立最大堆
void build_max_heap(int* a, int count)
{
	for (int i = count / 2; i >= 0; i--)    //count/2代表为最后一个非叶子结点
	{
		//对每个子根节点进行堆调整
		max_heapify(a, i, count);
	}
}

//返回优先度最大的对象
int heap_maximum(int* a)
{
	return a[0];
}

//返回并删除优先度最大的对象
int heap_extract_max(int* a, int count)
{
	if (count < 1)
		return -1;
	int max = a[0];                    //保存优先度最大的数
	a[0] = a[count];
	max_heapify(a, 0, count - 1);
	return max;
}

//增加元素的优先度
void heap_increase_key(int* a, int i, int key)    //key是需要改变元素的优先度,i代表第几个结点
{
	if (a[i] >= key)
		return;
	a[i] = key;
	while (i > 0 && a[(i - 1) / 2] < a[i])        //判断 改变优先度后是否小于双亲结点,以此不断向上
	{
		int t = a[(i - 1) / 2];
		a[(i - 1) / 2] = a[i];
		a[i] = t;
		i = (i - 1) / 2;
	}
}

//插入元素
int* heap_insert(int* a, int key, int count)
{
	int* p = (int*)malloc((count + 1) * 2);   //因为要返回出p所指向的内存,所以在里面分配内存空间
	for (int i = 0; i < count; i++)           //将原来的值加入到新的数组p中
	{
		p[i] = a[i];
	}
	p[count] = -1;
	heap_increase_key(p, count, key);
	return p;
}

void main11()
{
	int count, *p;
	printf("请输入需要排序的数的个数 :");
	scanf_s("%d", &count);
	p = (int*)malloc(count * 2);
	printf("\n请输入需要排序的%d个数字:", count);
	for (int i = 0; i < count; i++)
	{
		scanf_s("%d", p + i);
	}
	//依据输入的一列数字,建出一个最大堆
	build_max_heap(p, count - 1);
	printf("建立最大堆后的数组:");
	for (int i = 0; i < count; i++)
	{
		printf("%d ", p[i]);
	}
	printf("\n\n");

	printf("最大元素为:%d\n", heap_maximum(p));
	printf("\n\n");
	printf("弹出最大元素:%d, 当前堆为:", heap_extract_max(p, count - 1));
	count--;
	for (int i = 0; i < count; i++)
	{
		printf("%d ", p[i]);
	}
	printf("\n\n");
	printf("增大第5个元素的优先度为10, 当前堆为:");
	heap_increase_key(p, 4, 10);
	for (int i = 0; i < count; i++)
	{
		printf("%d ", p[i]);
	}
	printf("\n\n");
	printf("插入一个优先度为100的元素,当前堆为:");
	p = heap_insert(p, 100, count);
	for (int i = 0; i < count + 1; i++)
	{
		printf("%d ", p[i]);
	}
	system("pause");
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值