排序算法
sort
基础
sort(a + l, a + r + 1); //按小于号规则排序
sort(a + l, a + r + 1, cmp); //用 cmp(a,b) 替代 a < b
sort(a.begin(), a.end());// vector
例子
cmp 写法
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100000;
int n;
struct Stu
{
string nam;
int score;
int id;
};
Stu a[MAXN + 5];
bool cmp(Stu x, Stu y)
{
if (x.score != y.score)
return x.score > y.score;
return x.id < y.id;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> a[i].nam >> a[i].score;
a[i].id = i;
}
sort(a + 1, a + n + 1, cmp);
for (int i = 1; i <= n; i++)
cout << a[i].nam << " " << a[i].score << "\n";
return 0;
}
重载运算符
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100000;
int n;
struct Stu
{
string nam;
int score;
int id;
};
bool operator<(const Stu &a, const Stu &b)
{
if (a.score != b.score)
return a.score > b.score;
return a.id < b.id;
}
Stu a[MAXN + 5];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> a[i].nam >> a[i].score;
a[i].id = i;
}
sort(a + 1, a + n + 1);
for (int i = 1; i <= n; i++)
cout << a[i].nam << " " << a[i].score << "\n";
return 0;
}
另一种重载运算符写法
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100000;
int n;
struct Stu
{
string nam;
int score;
int id;
bool operator<(const Stu &b) const
{
if (score != b.score)
return score > b.score;
return id < b.id;
}
};
Stu a[MAXN + 5];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> a[i].nam >> a[i].score;
a[i].id = i;
}
sort(a + 1, a + n + 1);
for (int i = 1; i <= n; i++)
cout << a[i].nam << " " << a[i].score << "\n";
return 0;
}
经典下标排序
#include <bits/stdc++.h>
using namespace std;
int n;
int a[1005];
int id[1005];
bool cmp(int x, int y)
{
if (a[x] != a[y])
return a[x] < a[y];
return x < y;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
id[i] = i;
}
sort(id + 1, id + n + 1, cmp);
for (int i = 1; i <= n; i++)
cout << id[i] << " ";
return 0;
}
简单排序
选择排序
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100000;
int n;
string nam[MAXN + 5];
int score[MAXN + 5];
int id[MAXN + 5];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> nam[i] >> score[i];
id[i] = i;
}
for (int i = 1; i <= n; i++)
{
for (int j = i + 1; j <= n; j++)
{
if (score[j] > score[i] ||
score[j] == score[i] && id[j] < id[i])
{
swap(nam[i], nam[j]);
swap(score[i], score[j]);
swap(id[i], id[j]);
}
}
}
for (int i = 1; i <= n; i++)
{
cout << nam[i] << " " << score[i] << "\n";
}
return 0;
}
冒泡排序
最优化写法:
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100000;
int n;
struct Stu
{
string nam;
int score, id;
};
Stu a[MAXN + 5];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> a[i].nam >> a[i].score;
a[i].id = i;
}
for (int i = 1; i <= n - 1; i++)
{
bool flag = false;
for (int j = 1; j <= n - i; j++)
if (a[j + 1].score > a[j].score)
swap(a[j], a[j + 1]), flag = true;
if (!flag)
break;
}
for (int i = 1; i <= n; i++)
{
cout << a[i].nam << " " << a[i].score << "\n";
}
return 0;
}
插入排序
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100000;
int n;
struct Stu
{
string nam;
int score, id;
};
Stu a[MAXN + 5];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> a[i].nam >> a[i].score;
a[i].id = i;
}
for (int i = 2; i <= n; i++)
for (int j = i; j > 1 && a[j].score > a[j - 1].score; j--)
swap(a[j], a[j - 1]);
for (int i = 1; i <= n; i++)
{
cout << a[i].nam << " " << a[i].score << "\n";
}
return 0;
}
多关键字计数排序
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100000;
int n;
struct Stu
{
string nam;
int score;
};
Stu a[MAXN + 5];
Stu b[MAXN + 5];
int cnt[751];
int sum[751]; // 不包括自己后缀和(有几个人比这个分数高)
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i].nam >> a[i].score;
for (int i = 1; i <= n; i++)
cnt[a[i].score]++;
sum[750] = 0;
for (int i = 749; i >= 0; i--)
// (>i) = (>i+1) + (==i+1)
sum[i] = sum[i + 1] + cnt[i + 1];
for (int i = 1; i <= n; i++)
{
// 先看看有几个人比 a[i] 分数高:sum[a[i].score]
// 算出来 a[i] 的排名:sum[a[i].score] + 1
// 把 a[i] 放到 b 数组的这个位置
b[sum[a[i].score] + 1] = a[i];
// 后面同样分数的人,排名要往后挪一位
sum[a[i].score] += 1;
}
for (int i = 1; i <= n; i++)
cout << b[i].nam << " " << b[i].score << "\n";
return 0;
}
高级排序
快速排序
模板
// 对 a[L] ~ a[R] 排序
mt19937 rnd(time(0));
void quick_sort(int a[], int L, int R)
{
if (L >= R)
return;
// 挑选key
int pos = rnd() % (R - L + 1) + L;
swap(a[L], a[pos]);
int key = a[L];
// 把序列划分成两部分
int i = L;
int j = R;
while (i < j)
{
while (j > i && a[j] >= key)
j--;
a[i] = a[j];
while (i < j && a[i] <= key)
i++;
a[j] = a[i];
}
a[i] = key;
// 对两部分分别排序
quick_sort(a, L, i - 1);
quick_sort(a, i + 1, R);
}
额外应用
#include <bits/stdc++.h>
using namespace std;
// 对 a[L] ~ a[R] 排序,保证 a[k] 的位置是正确的
mt19937 rnd(time(0));
void kth(int a[], int L, int R, int k)
{
if (L >= R)
return;
// 挑选key
int pos = rnd() % (R - L + 1) + L;
swap(a[L], a[pos]);
int key = a[L];
// 把序列划分成两部分
int i = L;
int j = R;
while (i < j)
{
while (j > i && a[j] <= key)
j--;
a[i] = a[j];
while (i < j && a[i] >= key)
i++;
a[j] = a[i];
}
a[i] = key;
// 看看还要怎么排
// L~i-1 i i+1~R
if (i == k)
return;
else if (k < i)
kth(a, L, i - 1, k);
else
kth(a, i + 1, R, k);
}
const int MAXN = 1000000;
int n, k;
int a[MAXN + 5];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n >> k;
for (int i = 1; i <= n; i++)
cin >> a[i];
kth(a, 1, n, k);
cout << a[k];
return 0;
}
STL 中的 nth_element
nth_element(a + 1, a + k, a + n + 1, cmp);
归并排序
模板
const int MAXN = 1000000;
int n;
int a[MAXN + 5];
int temp[MAXN + 5];
void merge_array(int L, int R)
{
int M = (L + R) / 2;
// L ~ M : M+1 ~ R
int pl = L, pr = M + 1;
int pt = L;
// 两边都还有东西,就比较
while (pl <= M && pr <= R)
{
if (a[pl] <= a[pr])
temp[pt++] = a[pl++];
else
temp[pt++] = a[pr++];
}
while (pl <= M)
temp[pt++] = a[pl++];
while (pr <= R)
temp[pt++] = a[pr++];
// 放回到 a 数组
for (int i = L; i <= R; i++)
a[i] = temp[i];
}
void merge_sort(int L, int R)
{
if (L >= R)
return;
int M = (L + R) / 2;
merge_sort(L, M);
merge_sort(M + 1, R);
merge_array(L, R);
}
额外应用
选择右边元素时,左边剩余元素形成的逆序对都被消除了
...
if (a[pl] <= a[pr])
temp[pt++] = a[pl++];
else
temp[pt++] = a[pr++], ans += M - pl + 1;
...
堆排序
模板
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1000000;
int n;
int a[MAXN + 5];
int tot; // 当前堆大小 a[1]~a[tot]
void up(int pos)
{
while (pos != 1 && a[pos] > a[pos / 2])
{
swap(a[pos], a[pos / 2]);
pos = pos / 2;
}
}
void down(int pos)
{
while (1)
{
int maxPos = pos;
if (pos * 2 <= tot && a[pos * 2] > a[maxPos])
maxPos = pos * 2;
if (pos * 2 + 1 <= tot && a[pos * 2 + 1] > a[maxPos])
maxPos = pos * 2 + 1;
if (maxPos != pos)
{
swap(a[pos], a[maxPos]);
pos = maxPos;
}
else
break;
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i];
for (int i = 2; i <= n; i++)
up(i);
tot = n;
for (int i = 1; i <= n - 1; i++)
{
swap(a[1], a[tot]);
tot--;
down(1);
}
for (int i = 1; i <= n; i++)
cout << a[i] << " ";
return 0;
}
额外应用
if (op == 1)
{
a[++tot] = x;
up(tot);
}
if (op == 2)
cout << a[1] << "\n";
if (op == 3)
{
swap(a[1], a[tot]);
tot--;
down(1);
}
分类: 模板
· 更新时间 2026-7-11 16:46:23