- 文章
- oi-wiki
- acwing
- 冒泡排序
- 桶排序
- 快速排序【重要】
- 模板
- 常用代码模板1——基础算法 - AcWing
- 不理解作者如何解决所有边界情况
- 常用代码模板1——基础算法 - AcWing
- 例题
- 借助快排的思想,sort不能解决的问题
- 模板
- 归并排序【重要】
- 借助归并排序的性质
- 可以解决求 逆序对 问题
- 利用归并排序中,合并的流程构造
- 模板
- sort_merge_sort.cpp
- 例题
- P1908 逆序对 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
- 【模板题】归并排序 求逆序对 模板
- P1908 逆序对 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
- 借助归并排序的性质
- sort应用,自定义排序方式
- 自定义比较函数cmp
- C++中的sort自定义排序函数_Daniel_lmz的博客-CSDN博客_c++ sort自定义排序
- 传入的参数类型和需要排序的数据类型一致,如果认为第一个参数比第二个小,也就是第一个参数需要排在第二个参数前面时返回true,反之返回 false。系统默认a<b时返回true,于是从小到大排。
- C++中的sort自定义排序函数_Daniel_lmz的博客-CSDN博客_c++ sort自定义排序
- 注意
- 数组是没有交换(赋值)运算符,所以建议用 结构体 代替 多维数组
- 例题
- P1093 [NOIP2007 普及组] 奖学金 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
- 偷懒:P1093 把从小到大先偷换成从大到小,排好之后再把数据换回来
- P1093 [NOIP2007 普及组] 奖学金 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
- 自定义比较函数cmp
- 字符串排序
- 文章,知识点
- string是可以直接比较的,按照字典序比较
- 例题
- P1012 [NOIP1998 提高组] 拼数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
- 正常字典序321>32,但如果这样排在本题就不合适了,因为32321比32132更优,由此得到启发,由a+b,b+a来决定字典序排序
- 考察:字典序排序但又要结合实际情况
- P1012 [NOIP1998 提高组] 拼数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
- 文章,知识点
- unique去重
- 其实我用了set去重(题解也是)
- 其他排序
- 见数据结构笔记
快速排序:
/*sort_quick_sort.cpp*/
#include<bits/stdc++.h>
using namespace std;
int q[100005];
void qs(int l, int r){
if(l>=r) return;
int i = l-1, j = r+1, x = q[l + r >> 1];
while(i<j){ //用do-while好理解,不要改,背这一个模板就行。快排要背模板,边界情况不好想
do i++; while(q[i]<x);
do j--; while(q[j]>x);
if(i<j) swap(q[i],q[j]);
}
qs(l, j);
qs(j+1, r);
}
int main(){
int n;scanf("%d", &n);
for(int i = 0; i<n; i++) scanf("%d", &q[i]);
qs(0,n-1);
for(int i = 0; i<n-1; i++) printf("%d ", q[i]);
printf("%d\n", q[n-1]);
return 0;
}
快速排序(注释版):
/*acwing版本*/
void quick_sort(int q[], int l, int r){
if (l >= r) return;
int i = l - 1, j = r + 1, x = q[l + r >> 1]; // 这里的左右各退一步,是受到了do while的影响,因为会先do,所以要退一步
while (i < j){ //用do-while好理解,不要改,背这一个模板就行。快排要背模板,边界情况不好想
do i ++ ; while (q[i] < x); //遇到等于x的就停下来了,交换完后(保证任何时刻),i左边的数(不包括i)<= x
do j -- ; while (q[j] > x);
if (i < j) swap(q[i], q[j]); // 直到i和j指向的位置都需要交换时,直接两个位置交换,达到原地的效果
} // 循环一次,分出左边是<=x的,右边是>=x的
quick_sort(q, l, j);
quick_sort(q, j + 1, r);
}
//do while结构,保证了i和j的不断移动,不会因为指向两个相等的数而停滞不前
//i x j 时:do i++, do j--, 如果x = i = j,变成ij重叠,ok
// j i
//j i
//1 i j 9 时:do i++, do j-- ,变成 1 j i 9, ok
//至于为什么是(q, l, j)与(q, j + 1, r),因为每次结束,要么ij重叠,要么 1 j i 9, 分界在j和j+1中间的位置
//l + r >> 1 是上取整还是下取整也会影响,用错会造成死循环,样例1 2
//下取整时候,用(q, l, j)与(q, j + 1, r)
//上取整时候,用(q, l, i-1)与(q, i, r);上取整操作x = q[l + r + 1>> 1]
归并排序:
/*sort_merge_sort.cpp*/
#include<bits/stdc++.h>
#define N 100005
using namespace std;
int tmp[N];
void merge_sort(int q[], int l, int r)//左闭右闭
{
if (l >= r) return;
int mid = l + r >> 1;//一般对半归并就行
merge_sort(q, l, mid);//左闭右闭
merge_sort(q, mid + 1, r);//左闭右闭
int k = 0, i = l, j = mid + 1;
while (i <= mid && j <= r)
if (q[i] <= q[j]) tmp[k ++ ] = q[i ++ ];
else tmp[k ++ ] = q[j ++ ];
while (i <= mid) tmp[k ++ ] = q[i ++ ];
while (j <= r) tmp[k ++ ] = q[j ++ ];
for (i = l, j = 0; i <= r; i ++, j ++ ) q[i] = tmp[j];
}
int main(){
int ms[] = {9,6,3,8,5,2,7,4,1,0};
merge_sort(ms,0,9);//左闭右闭
return 0;
}