排序算法整理

105 阅读5分钟

P1177 【模板】排序 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

一道模板题,没有什么好讲的,想记录的是最后的换行判断,具体看代码:

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main() {
	int n;
	cin >> n;
	vector<int>a(n, 0);// 开个大小为n的vector,后加逗号 零指的是里面的数字全部初始化为零,大小为n,下标就是从0到n-1 
	for (int i = 0; i < n; i++) {
		cin >> a[i];
	}
	sort(a.begin(), a.end());//这种是针对容器的做法,具体不了解
	for (int i = 0; i < n; i++) {
		cout << a[i] << " \n"[i == n - 1];
	}

	return 0;
}

重点留意下最后的换行判断,很少见这种写法。

P1059 [NOIP2006 普及组] 明明的随机数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include<iostream>
#include<algorithm>
using namespace std;
int const MAXN = 1010;
int a[MAXN], ans[MAXN], n, cnt = 0, tmp = -1;//假设tmp为-1,这样可以后续循环判断是否有重复的数字。只要tmp小于1即可。
int main() {
	cin >> n;
	for (int i = 0; i < n; i++) {
		cin >> a[i];
	}
	sort(a, a + n);
	for (int i = 0; i < n; i++) {
		if (a[i] != tmp) {
			ans[cnt++] = a[i];//赋值后cnt再加1.
			tmp = a[i];//,将当前最大值赋给tmp,如果和tmp相同,则去重,否则加入ans中,并且更新tmp的值
		}
	}
	cout << cnt << endl;
	for (int i = 0; i < cnt; i++) {//注意这里i是要小于cnt,否则还是会输出相同数量的元素,但是变为零
		cout << ans[i] << " ";
	}
	return 0;
}

以前写的代码,跟现在的思路完全不一样,现在想的是桶排序,虽然桶排序更优,但是原来的这种做法也有一定的学习意义,注释都写得很清楚了。

桶排序懒得写了,直接看题解里面得代码吧,上链接:(第一份就是桶排序)

P1059 [NOIP2006 普及组] 明明的随机数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

看看另外一道题目:

P1093 [NOIP2007 普及组] 奖学金 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

这里主要回顾一下自定义排序函数的写法,代码贴在下面:

#include<iostream>
#include<algorithm>
using namespace std;
int const MAXN = 310;
int n;
struct student {
	int id, total, chinese;
}a[MAXN];
int cmp(student a, student b) {
	if (a.total != b.total)return a.total > b.total;
	if (a.chinese != b.chinese)return a.chinese > b.chinese;
	return a.id < b.id;
}
int main() {
	cin >> n;
	for (int i = 0; i < n; i++) {
		int math, english;
		cin >> a[i].chinese >> math >> english;
		a[i].total = a[i].chinese + english + math;
		a[i].id = i + 1;
	}
	sort(a, a + n, cmp);
	for (int i = 0; i < 5; i++) {
		cout << a[i].id << " " << a[i].total << endl;
	}
	return 0;
}

主要还是得看清楚题目要求,写合适的cmp函数。

再看看这道相似的题目,是上面的拓展:

P1781 宇宙总统 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include<iostream>
#include<algorithm>
using namespace std;
struct mem {
	string x;
	int num;
}s[25];
bool cmp(mem a, mem b) {
	if (a.x.length() != b.x.length()) {
		return a.x.length() > b.x.length();
	}
	return a.x > b.x;
}
int n;
int main() {
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> s[i].x;
		s[i].num = i;
	}
	sort(s + 1, s + 1 + n, cmp);
	cout << s[1].num << endl << s[1].x;
	return 0;
}

注意:题目提示说票数可能超过100位,所以我们就不能使用整型进行比较,而是利用字符串,显而易见的:长度长的代表的数字肯定更大,如果相同,再比较对应的大小。

P2676 [USACO07DEC] Bookshelf B - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 简单题,不讲,可以练练。

P1152 欢乐的跳 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

简单题,桶排序就行,可以练练。

另外看到题解区有位大佬写的题解,很有学习价值,可以看看。

题解 P1152 【欢乐的跳】 - 菜MKのblog - 洛谷博客 (luogu.com.cn)

再看看另外一道练手题:

P1116 车厢重组 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

其实就是冒泡排序。

P1068 [NOIP2009 普及组] 分数线划定 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

这道题要注意的是:可能会有选手达到分数线,但是这时候超过预定人数的情况,只需要以分数是否大于分数线判断即可。

P1104 生日 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

P5143 攀爬者 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

都是简单题,可以练练。

P1012 [NOIP1998 提高组] 拼数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

这道题目有点意思,我一开始没想出怎么写,看了题解之后只感觉太奇妙了,代码如下:

#include<iostream>
#include<algorithm>
using namespace std;
string a[25];
int n;
bool cmp(string a, string b) {
	return a + b > b + a;
}
int main() {
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
	}
	sort(a + 1, a + 1 + n, cmp);
	for (int i = 1; i <= n; i++) {
		cout << a[i];
	}
	cout << endl;
	return 0;
}

这个相信大家都能看懂,具体分析还是看看题解吧:

P1012 [NOIP1998 提高组] 拼数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

P1923 【深基9.例4】求第 k 小的数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

快排的板子题,可以练练手,还可以学一下nth_element函数。快排的代码如下:

#include <iostream>
#define rep(i, a, b) for (int i = a; i <= (b); i++)
using namespace std;
int arr[5000000], n, k;
void qksort(int a[], int l, int r) {
	int pos = l + r >> 1, i = l, j = r - 1;
	swap(a[pos], a[r]);
	do {
		while (i <= j && a[i] < a[r])
			i++;
		while (i <= j && a[j] > a[r])
			j--;
		if (i <= j) {
			swap(a[i], a[j]);
			i++;
			j--;
		}
	} while (i <= j);
	swap(a[i], a[r]); // 一定有 l<=i<=r && a[i]>=a[r](a[r]即flag)
	if (i > k)
		qksort(a, l, i - 1);
	else if (i < k)
		qksort(a, i + 1, r);
}
int main() {
	ios_base::sync_with_stdio(0), cin.tie(0);
	cin >> n >> k;
	rep(i, 0, n - 1) {
		cin >> arr[i];
	}
	qksort(arr, 0, n - 1);
	cout << arr[k];

	return 0;
}

想学nth_element函数的话,看看题解区吧:

P1923 【深基9.例4】求第 k 小的数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

总结一句话: 函数语句:nth_element(数组名,数组名+第k小元素,数组名+元素个数)。