排序算法学习
时间复杂度为O(n²)的三种排序方法、基于比较的三种排序方法
选择排序
基本思路:从 i 到 n - 1 依次遍历,找出最值与当前位置互换
简单优化:可以同时记录最大值和最小值,两边开工
变式解决问题:最小交换次数
代码实现
void mysort(int s[], int n) { for (int i = 0; i < n - 1; i++) { int minpos = i; for (int j = i + 1; j < n; j++) { if (s[j] < s[minpos]) minpos = j; } if (minpos != i) { int tmp = s[i]; s[i] = s[minpos]; s[minpos] = tmp; } } }
冒泡排序
基本思路:进行不断比较
简单优化:
- 可以使用nflags记录是不是有交换,如果没有交换那么停止排序;
- 使用一个数记录最后面的交换的地方,在这个数字后面的数字无需交换
代码实现
void mysort(int s[], int n) { int last = n - 1; int nflags = 0; do { nflags = 0; int tmp_last = 0; for (int i = 0; i < last; i++)//注意:循环变量在循环内部一定不能改变 { if (s[i] > s[i + 1]) { int tmp = s[i + 1]; s[i + 1] = s[i]; s[i] = tmp; nflags = 1; tmp_last = i ; } } last = tmp_last; } while (nflags); }
插入排序(简单版本)
不断进行对比,然后插入。
三种不基于比较的排序(时间复杂度为O(n), 但是数据的变化范围要尽可能地小)
计数排序(桶排序的变种)
注意,如果是成绩等等数据范围有限的数字排列,桶排序的时间复杂度竟然是O( n )全场最低
#include <iostream> #include <map> using namespace std; int a[1000]; int b[1000]; map<int, int >bucket; void my_sort(int* s, int n) { int max_num = s[0]; int min_num = s[0]; map<int, int >t; for (int i = 0; i < n; i++) { if (s[i] > max_num) max_num = s[i]; if (s[i] < min_num) min_num = s[i]; t[s[i]]++; } for (int i = min_num,k = 0; i <= max_num; i++) { int pos = 0; while (t[i]--) s[k++] = i; } } void print(int s[], int n) { for (int i = 0; i < n; i++) cout << s[i] << ' '; } int main() { int n; cin >> n; for (int i = 0; i < n; i++) cin >> a[i]; my_sort(a, n); print(a, n); }
基数排序
类似于桶排序:
- 但是可以更好地在内存不够的情况下拓展桶排序的数目(可以设置的位数不一定是一位,还可以多次设置)
- 可以完成多级排序
重点是类似于队列,不同队列,从左到右,相同队列,从前到后
避坑:从优先级最后按照顺序向前排列
代码实现
#include <iostream> #include <map> #include <cmath> using namespace std; int a[1000]; int b[1000]; void jishupaixu(int *s, int n) { for (int t = 0; t < 10; t++) { int a[10][1000] = { 0 }; int pos[10] = { 0 }; int shang = pow(10, t); for (int i = 0; i < n; i++) { int hs = s[i] / shang % 10; a[hs][(pos[hs]++)] = s[i]; } for (int i = 0, p = 0; i < 10; i++) { for (int j = 0; j < pos[i]; j++) { s[p++] = a[i][j]; } } } } void print(int s[], int n) { for (int i = 0; i < n; i++) cout << s[i] << ' '; } int main() { int n; cin >> n; for (int i = 0; i < n; i++) cin >> a[i]; jishupaixu(a, n); print(a, n); }
桶排序
桶排序确实比较拉胯,它的意思是分一些桶,把数据放在一个区间范围内的桶中,然后分别排每一个桶,最后输出;
但是桶的数据结构也很拉胯,
- 数组会增加空间消耗
- vector会增加时间消耗
- list直接是冒泡排序级别的
所以一般不用,如果要使用,就是先分成几个区间中的桶,然后对每个桶使用sort。。。。。。。。。
两种大神级别排序
归并排序
代码实现
- 注意这里有一个临时数组:b
- 在归并实现的时候:
- 是左右两个数组比较后放入备份数组
- 是否有效,即有没有用完
- 大小关系
- 是左右两个数组比较后放入备份数组
#include <iostream> using namespace std; int a[1000]; int b[1000]; void my_sort(int l, int mid, int r) { int lpos = l, rpos = mid + 1; for (int i = l; i <= r; i++) { if (lpos <= mid && (a[lpos] <= a[rpos] || rpos > r)) { b[i] = a[lpos++]; } else { b[i] = a[rpos++]; } } for (int i = l; i <= r; i++) a[i] = b[i]; } void dive(int l, int r) { int mid = (l + r) / 2; if (l < r) { dive(l, mid); dive(mid + 1, r); } my_sort(l, mid, r); } void print(int s[], int n) { for (int i = 0; i < n; i++) cout << s[i] << ' '; } int main() { int n; cin >> n; for (int i = 0; i < n; i++) cin >> a[i]; dive(0, n - 1); print(a, n); }
快速排序
#include <iostream> using namespace std; int a[1000]; int b[1000]; void quike_sort(int l, int r) { int i = l; int j = r; int mid = (l + r) >> 1; int t = a[mid];//一定要拿出这个基准值,因为后面会变化 while (i <= j) { while (a[i] < t) i++;//一定是小于,为了让左指针在基准值之前停留下来 while (a[j] > t) j--;//同上 if (i <= j) { int tmp = a[i]; a[i] = a[j]; a[j] = tmp; i++; j--; } } if (l < j) quike_sort(l, j); if (i < r) quike_sort(i, r); } void print(int s[], int n) { for (int i = 0; i < n; i++) cout << s[i] << ' '; } int main() { int n; cin >> n; for (int i = 0; i < n; i++) cin >> a[i]; quike_sort(0, n-1); print(a, n); }
本文来自博客园,作者:心坚石穿,转载请注明原文链接:https://www.cnblogs.com/xjsc01/p/15761304.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了