温馨提示:本文章不会讲一些正经排序,如果想阅读正经排序请出门右转到这里
测试题目:模板排序
一、猴子排序
如果一只猴子一直敲键盘,总能敲出莎士比亚全集。猴子排序的思想也类似,随机打乱数组,然后判断是否是一个有序序列。
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 5;
int n, a[MAXN];
bool is_order(int *a, int n) {
for (int i = 2; i <= n; i++)
if (a[i - 1] > a[i]) return false;
return true;
}
void monkey_sort(int *a, int n) {
while (!is_order(a, n))
random_shuffle(a + 1, a + 1 + n);
}
int main() {
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
monkey_sort(a, n);
for (int i = 1; i <= n; i++) cout << a[i] << " ";
return 0;
}
复杂度为 ,稳定
二、指针排序(侏儒排序)
侏儒排序的思想很简单。如果当前数小于后面的数,就交换两个数,然后指针往后退(当然,有边界)。详见代码:
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 5;
int n, a[MAXN];
void stupid_sort(int *a, int n) {
for (int i = 1; i <= n;)
if (i == 1 || a[i] >= a[i - 1]) i++;
else swap(a[i], a[i - 1]), i--;
}
int main() {
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
stupid_sort(a, n);
for (int i = 1; i <= n; i++) cout << a[i] << " ";
return 0;
}
最坏的时间复杂度为,稳定。
三、脸黑排序
说实话,这个排序的思想很简单。输入时记录极值,然后在这个范围乱搞就行了。
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
int a[n];
int minn = 10000000;
int maxx = -1000000;
for (int i = 1; i <= n; i++) {
cin >> a[i];
maxx = max(maxx, a[i]);
minn = min(minn, a[i]);
}
for (int i = minn; i <= maxx; i++) {
for (int j = 1; j <= n; j++) {
if (a[j] == i) {
cout << a[j] << " ";
}
}
}
return 0;
}
时间复杂度,其中A为数组中最大值,B为数组中最小值。
四、区间排序
两两一组,进行排序,再把边界往后挪,
#include<iostream>
using namespace std;
const int size = 1e+7;
int n,a[size],opr;
int main(){
cin >> n;
for(int i = 1;i <= n;i++) cin >> a[i];
for(int i = 1;i <= n * (n / 2 + 1);i++){
opr = i % (n - 1) + 1;
while(opr <= n){
if(a[opr - 1] > a[opr]) swap(a[opr - 1],a[opr]);
opr += 2;
}
}
for(int i = 1;i <= n;i++) cout << a[i] << " ";
}
时间复杂度为
五、排列排序
类似于猴子排序,不过将脸黑系统改成了全排列而已,更稳定
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
int n,str[100005];
bool k = true;
cin >> n;
for(int i = 1;i <= n;i++) cin >> str[i];
do {
for(int i = 1;i <= n;i++){
if(str[i] < str[i + 1]){
k = false;
break;
}
}
if(k == true){
for(int i = n;i >= 1;i--) cout << str[i] << " ";
return 0;
}
k = true;
} while (next_permutation(str + 1,str + n + 1));
}
时间复杂度为
六、沉淀排序
将每个元素每次减一,如果为0则输出
#include<bits/stdc++.h>
using namespace std;
const int size = 1e+7;
int a[size],b[size],n,minn=INT_MAX;
bool k = true;
int main(){
cin >> n;
for(int i = 1;i <= n;i++){
cin >> a[i];
b[i] = a[i];
minn = min(minn,a[i]);
}
for(int i = 1;i <= n;i++) b[i]-=minn;
for(int i = 1;i <= n;i++){
while(1){
for(int j = 1;j <= n;j++){
if(!b[j]){
cout << a[j] << " ";
b[j] = INT_MAX;
k = false;
}
b[j]--;
}
if(!k){
k = true;
break;
}
}
}
}
复杂度为
七、Hash去重排序
这个算法的核心是用Hash表的思想进行存储,再在极值里面乱搞就行。
#include<iostream>
#include<algorithm>
using namespace std;
const int size = 1e+7;
int a[size],n;
int Hash[size],maxx = INT_MIN,minn = INT_MAX;
int main(){
cin >> n;
for(int i = 1;i <= n;i++){
cin >> a[i];
Hash[a[i]] = a[i];
maxx = max(a[i],maxx);
}
for(int i = 0;i <= maxx;i++){
if(Hash[i]) cout << Hash[i] << " ";
}
}
但这个算法会自带去重,所以做明明的随机数很合适 。
时间复杂度为
但有个前提就是数据范围不能超过1e+8,必须小于1e+8.