【数据结构】【堆】【排序】堆 && 堆排序

本文介绍了堆数据结构和堆排序的相关知识。通过样例输入输出解析了如何处理堆的操作,提出使用堆和STL队列来实现小根堆,并讨论了堆排序的思路,强调了在解决堆排序问题时避免使用内置排序函数,而是手动实现堆排序算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言:

推介配合lyf巨爷的一些来自STL的好东西


题目:

如题,初始小根堆为空,我们需要支持以下3种操作:

操作1: 1 x 表示将x插入到堆中

操作2: 2 输出该小根堆内的最小数

操作3: 3 删除该小根堆内的最小数


输入:

输入格式:
第一行包含一个整数N,表示操作的个数

接下来N行,每行包含1个或2个正整数,表示三种操作,格式如下:

操作1: 1 x

操作2: 2

操作3: 3


输出:

包含若干行正整数,每行依次对应一个操作2的结果。


样例输入:

5
1 2
1 5
2
3
2

样例输出:

2
5

思路:

其实就只有三种操作,如何模拟三种操作是这题的难点,那要怎么模拟呢?暴力吗,二分吗?都不是,用堆+STL队列来做,用堆里面的小根堆(其实就是特殊的优先队列(越小的整数优先级越大))

priority_queue<int,vector<int>,greater<int> >q;

C o d e Code Code

#include<cstdio>
#include<iostream>
#include<queue>
using namespace std;
priority_queue<int,vector<int>,greater<int> >gg;//定义小根堆
int n,x;
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++) 
	{
	  scanf("%d",&x);
	  if(x==1){scanf("%d",&x);gg.push(x);}//在小根堆中插入x
	  else if(x==2)printf("%d\n",gg.top());//输出元素
	  else gg.pop();//删除最小元素
	}
return 0;
	
}

堆排序

题目:

输入 n 个数,要求用堆排序输出从小到大排完序后的结果


输入:

第一行输入 n (n<=200000),表示元素个数。
接下来 n 行输入这 n 个数 (longint范围内)。


输出:

输出N个数,每行1个数,按照从小到大的顺序输出。


样例输入:

4
3
2
4
1

样例输出:

1
2
3
4


思路:

首先n<=200000就确定了sort要滚蛋,所以我们用堆排序,然后这次不用STL,手打函数,其实也不难,就一个‘=‘坑了我一个下午+晚上


C o d e Code Code

#include<cstdio>
#include<iostream>
using namespace std;
int a[300000],px[300000],n,t;
void down(int dep)//下移
{
	while((dep*2<=t && px[dep]>px[dep*2]) || (dep*2+1<=t && px[dep]>px[dep*2+1]))
	{
	  int yi=dep*2;
	  if((yi+1<=t )&& (px[yi+1]<px[yi])) yi++;
	  swap(px[dep],px[yi]);
	  dep=yi;
    }
}
void up(int dep)//上移
{
	while((dep>1) && (px[dep]<px[dep/2]))
	{
		swap(px[dep],px[dep/2]);
		dep/=2;
	}
}
void jian(int dep)//建堆
{
	++t;
	px[t]=a[dep];
	up(t);
}
void breakk(int dep)//删数
{
	if(px[t]>px[dep])
	{
		px[dep]=px[t--];
		down(dep);
	}
	else {
		px[dep]=px[t--];
		up(dep);
	}
}
int main()
{	
  scanf("%d",&n);
  for(int i=1;i<=n;i++)
  {
    scanf("%d",&a[i]);
    jian(i);//建堆
  }
  int xh=t;//输出的次数
  for(int i=1;i<=xh;i++)
  {
  	printf("%d\n",px[1]);//输出堆顶(最小)
  	breakk(1);//(删掉堆顶)
  }
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值