数据结构 排序
归并排序
插入排序
直接插入排序
基本思想:
每步将一个待排序的元素,插入到已经排好序的一组元素的适当位置上去,直到元素全部插入为止。
基本操作:
- 将待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列;
- 取出下一个元素,在已经排序的元素序列中从后向前扫描;
- 如果该元素(已排序)大于新元素,将该元素移到下一位置;
- 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;
- 将新元素插入到该位置后;
- 重复步骤2~5。
图示:
代码
#include <bits/stdc++.h> using namespace std; typedef long long ll; #define PII pair<int, int> #define x first #define y second const int maxn = 1e6 + 10; const int INF = 0x3f3f3f3f; const ll M = 1e9 + 7; const int N = 10010; int a[maxn]; void insertion_sort(int len) { // 对每个元素 for (int i = 1; i < len; ++i) { int key = a[i]; int j = i - 1; // 插入合适的位置 while (j >= 0 && a[j] > key) { a[j + 1] = a[j]; j--; } a[j + 1] = key; } } int main() { int n; cin >> n; for (int i = 0; i < n; i++) { cin >> a[i]; } //排序 insertion_sort(n); //输出 for (int i = 0; i < n; i++) { if (i == n - 1) cout << a[i] << endl; else cout << a[i] << " "; } return 0; }
插入排序转自
希尔排序
思想:
对于n个元素的待排序的数列,
- 取一个小于n的整数gap(gap被称为步长)将待排序元素分成若干个组子序列,所有距离为gap的倍数的记录放在同一个组中;
- 然后,对各组内的元素进行直接插入排序。 这一趟排序完成之后,每一个组的元素都是有序的。
- 然后减小gap的值,并重复执行上述的分组和排序。重复这样的操作,当gap=1时,整个数列就是有序的。
图示
特点:
- 一次移动移动位置大,跳远的接近排序后的最终位置。
- 增量序列必须递减,最后一个必须是1
- 增量序列应该是互质的
希尔排序是不稳定排序
希尔排序的时间复杂度
与增量(即,步长gap)的选取有关。例如,当增量为1时,希尔排序退化成了直接插入排序,此时的时间复杂度为O(N²),而Hibbard增量的希尔排序的时间复杂度为O(N3/2)。
代码
#include <bits/stdc++.h> using namespace std; typedef long long ll; #define PII pair<int, int> #define x first #define y second const int maxn = 1e6 + 10; const int INF = 0x3f3f3f3f; const ll M = 1e9 + 7; const int N = 10010; int a[maxn]; int n; void xisort(int x) { for (int i = x; i < n; i++) { for (int j = i - x; j >= 0; j -= x) { if (a[j] > a[j + x]) { swap(a[j], a[j + x]); } } } } int main() { while (cin >> n) { for (int i = 0; i < n; i++) { cin >> a[i]; } int dk = n / 2; xisort(dk); for (int i = 0; i < n; i++) { if (i == n - 1) cout << a[i] << endl; else cout << a[i] << " "; } dk = 1; xisort(dk); for (int i = 0; i < n; i++) { if (i == n - 1) cout << a[i] << endl; else cout << a[i] << " "; } } return 0; }
交换排序
冒泡排序
思想
基本思想
- 将序列当中的左右元素,依次比较,保证右边的元素始终大于左边的元素;
( 第一轮结束后,序列最后一个元素一定是当前序列的最大值;) - 对序列当中剩下的n-1个元素再次执行步骤1。
- 重复多次,直到有序。
时间复杂度
On2
辅助空间:
O1
稳定性
稳定的
代码
代码1:常用
#include <bits/stdc++.h> using namespace std; typedef long long ll; #define PII pair<int, int> #define x first #define y second const int maxn = 1e6 + 10; const int INF = 0x3f3f3f3f; const ll M = 1e9 + 7; const int N = 10010; int a[maxn]; int main() { int n; cin >> n; for (int i = 0; i < n; i++) { cin >> a[i]; } //排序 for (int i = 0; i < n - 1; i++) { for (int j = 0; j < n - 1 - i; j++) { if (a[j] > a[j + 1]) { swap(a[j], a[j + 1]); } } } //输出 for (int i = 0; i < n; i++) { if (i == n - 1) cout << a[i] << endl; else cout << a[i] << " "; } return 0; }
代码2:抽出函数体
#include <bits/stdc++.h> using namespace std; typedef long long ll; #define PII pair<int, int> #define x first #define y second const int maxn = 1e6 + 10; const int INF = 0x3f3f3f3f; const ll M = 1e9 + 7; const int N = 10010; int a[maxn]; //一次冒泡 void bubble(int n){ for(int i=0;i<n-1;i++){ if(a[i]>a[i+1]){ swap(a[i],a[i+1]); } } } void bubbleSort(int n){ for(int i=n;i>=1;i--){ bubble(i); } } int main() { int n; cin>>n; for (int i = 0; i < n; i++) { cin >> a[i]; } bubbleSort(n); //输出 for (int i = 0; i < n; i++) { if (i == n - 1) cout << a[i] << endl; else cout << a[i] << " "; } return 0; }
快速排序
基本思想:
- 从序列当中选择一个基准数(pivot)
一般选择序列当中第一个数为基准数 - 将序列当中的所有数依次遍历,比基准数大的位于其右侧,比基准数小的位于其左侧,形成两个子表。
- 对子表重复步骤1.2,直到所有子集当中只有一个元素为止。
时间复杂度
平均时间最快。
越乱速度越快,基本有序的情况下On2。
快速排序不是原地排序
需要O logn的栈空间。
最快是O n
快速排序不是稳定排序
代码
注意:只能先进行while(i<j&&a[j]>=tmp)j--;
#include <bits/stdc++.h> #define pii pair<int, int> using namespace std; int a[900000]; int n; void q_sort(int l, int r) { if (l >= r) return; int tmp = a[l]; int i=l,j=r; while(i<j){ while(i<j&&a[j]>=tmp)j--; while(i<j&&a[i]<=tmp)i++; swap(a[i],a[j]); } swap(a[l],a[i]); // int mid=(l+r)/2; q_sort(l, i - 1); q_sort(i + 1, r); } int main() { cin >> n; for (int i = 0; i < n; i++) { cin >> a[i]; } q_sort(0, n - 1); for (int i = 0; i < n; i++) { cout << a[i] << " "; } cout<<endl; return 0; }
选择排序
简单选择排序
基本思想:
在待排序的数据中选出最大(小)的元素放在其最终的位置。
基本操作:
- 首先通过n-1次关键字比较,从n个记录中找出关键字最小的记录,将 它与第一个记录交换
- 再通过n-2次比较,从剩余的n-1个记录中找出关键字次小的记录,将它与第二个记录交换
- 重复上述操作,共进行n-1趟排序后,排序结束
图示:
代码
#include <bits/stdc++.h> using namespace std; typedef long long ll; #define PII pair<int, int> #define x first #define y second const int maxn = 1e6 + 10; const int INF = 0x3f3f3f3f; const ll M = 1e9 + 7; const int N = 10010; int a[maxn]; int findMaxPos(int n) { int maxNumber = a[0]; int maxid = 0; for (int i = 0; i < n; i++) { if (a[i] > maxNumber) { maxNumber = a[i]; maxid = i; } } return maxid; } void selectionSort(int n) { while (n > 1) { int maxid = findMaxPos(n); swap(a[maxid], a[n - 1]); n--; } } int main() { int n; cin >> n; for (int i = 0; i < n; i++) { cin >> a[i]; } //排序 selectionSort(n); //输出 for (int i = 0; i < n; i++) { if (i == n - 1) cout << a[i] << endl; else cout << a[i] << " "; } return 0; }
堆排序
本文作者:kingwzun
本文链接:https://www.cnblogs.com/kingwz/p/15747401.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步