1.计数排序讲解
在讲解计数排序之前,我想先请大家思考这样一个问题:
小A的班上只有5个人,他们的成绩分别是5分,2分,3分,5分,4分。请你将他们的成绩按从大到小的规则排序。
“我直接一个sort
搞定收工”是不行的,请大家思考其它的做法
我们可以将这些分数分成不同的编号的旗子。
定义一个大小为n
的一维数组,也就是一堆从1到n的编号的桶子。
我们需要将旗子和桶子一一对应,也就是将n
号旗子放到n
号桶子里面去。
最后计算每个桶子内旗子的数量一一输出。代码如下:
#include<bits/stdc++.h>
using namespace std;
int main(){
int n, a[15] = {};//一定要将数组初始化为0,这是很多初学者都会犯的错误
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
int tmp;
scanf("%d", &tmp);
a[tmp]++;//放进桶中
}
for (int i = 0; i <= 10; i++)//循环到每个可能出现的数都判断到
while (a[i]) {
printf("%d ", i);
a[i]--;//输出了一次,还剩下的数量减一
}
return 0;
}
上面的代码就使用了计数排序的思想。
输入5 5 2 3 5 4
时,桶内情况如下:
桶1(下标1) | 桶2(下标2) | 桶3(下标3) | 桶4(下标4) | 桶5(下标5) | … |
---|---|---|---|---|---|
0 | 1 | 1 | 1 | 2 | 0 |
其中,每个桶内的数量(即a[i]
)就可以看做考i
分的同学的数量,这也是计数排序名称的由来。它还有两个好兄弟:桶排序和基数排序,千万不要搞混了。我以前就把计数排序叫做桶排序。 刚入门就只需要学习最简单的计数排序就行了。
桶排序有很多优点,比如时间复杂度只有
O
(
n
+
w
)
O(n+w)
O(n+w)(
w
w
w为值域,即要排序的数字最大是多少),访问某个数有多少快等。但它也有很多缺点,比如无法将名字等信息和数字一一对应,浪费空间(比如排序1 200001 198341 199999
),无法排序负数和小数等。
如果还想练习计数排序可以去看看洛谷 P7072 [CSP-J2020] 直播获奖,题解在这【题解】【排序】—— [CSP-J2020] 直播获奖。
2.【深基9.例1】选举学生会
题目描述
学校正在选举学生会成员,有 n n n( n ≤ 999 n\le 999 n≤999)名候选人,每名候选人编号分别从 1 1 1 到 n n n,现在收集到了 m m m( m ≤ 2000000 m \le 2000000 m≤2000000)张选票,每张选票都写了一个候选人编号。现在想把这些堆积如山的选票按照投票数字从小到大排序。
输入格式
输入 n n n 和 m m m 以及 m m m 个选票上的数字。
输出格式
求出排序后的选票编号。
输入输出样例
输入 #1
5 10
2 5 2 2 5 2 2 2 1 2
输出 #1
1 2 2 2 2 2 2 2 5 5
2.1.题意解析
这道题我们可以直接模拟每个投票箱,已达到排序的效果,具体原理不再赘述。直接看代码。
2.2.AC代码
#include<bits/stdc++.h>
using namespace std;
#define MAXN 200010
int main()
{
int n,m,tmp,a[MAXN]={},i;
cin>>n>>m;
for(i=1;i<=m;i++)//将数字放入桶里
{
cin>>tmp;
a[tmp]++;
}
for(i=1;i<=MAXN-10;i++)//每个桶都判断到,注意值最大为MAN-10
while(a[i])//只要这个数字出现了
{
cout<<i<<' ';
a[i]--;
}
return 0;
}
喜欢就订阅此专辑吧!
【蓝胖子编程教育简介】
蓝胖子编程教育,是一家面向青少年的编程教育平台。平台为全国青少年提供最专业的编程教育服务,包括提供最新最详细的编程相关资讯、最专业的竞赛指导、最合理的课程规划等。本平台利用趣味性和互动性强的教学方式,旨在激发孩子们对编程的兴趣,培养他们的逻辑思维能力和创造力,让孩子们在轻松愉快的氛围中掌握编程知识,为未来科技人才的培养奠定坚实基础。
欢迎扫码关注蓝胖子编程教育