O(nlogn)排序算法
排序算法
介绍常见时间复杂度为的排序算法
注意:本文图文并茂
将提供以下图文链接供大家理解:
图文链接:
飞书图解链接🎉🎉🎉
密码:9531F#72
1. 快速排序
分治思想
#include<bits/stdc++.h> using namespace std; const int N = 1e5 + 10; int a[N]; void quick_sort(int l, int r){ if(l >= r) return; int x = a[l + r >> 1], i = l - 1, j = r + 1; while(i < j){ while(a[ ++ i] < x); while(a[ -- j] > x); if(i < j) swap(a[i], a[j]); } quick_sort(l, j), quick_sort(j + 1, r); } int main(){ int n; scanf("%d", &n); for(int i = 0; i < n; i ++ ) scanf("%d", &a[i]); quick_sort(0, n - 1); for(int i = 0; i < n; i ++ ) printf("%d ", a[i]); return 0; }
题目一
#include<bits/stdc++.h> using namespace std; const int N = 5e6 + 10; int a[N], n, k; // k代表索引 int quick_sort(int l, int r){ if(l >= r) return a[l]; int x = a[l + r >> 1], i = l - 1, j = r + 1; while(i < j){ while(a[ ++ i] < x); while(a[ -- j] > x); if(i < j) swap(a[i], a[j]); } if(k <= j) return quick_sort(l, j); return quick_sort(j + 1, r); } int main(){ scanf("%d%d", &n, &k); for(int i = 0; i < n; i ++ ) scanf("%d", &a[i]); printf("%d", quick_sort(0, n - 1)); return 0; }
题目二
#include<bits/stdc++.h> using namespace std; const int N = 1e4 + 10; int a[N], n, k, t, len; // k代表索引, t暂存数据, len表示a数组的长度 bool c[N]; // bool数组 int quick_sort(int l, int r){ if(l >= r) return a[l]; int x = a[l + r >> 1], i = l - 1, j = r + 1; while(i < j){ while(a[ ++ i] < x); while(a[ -- j] > x); if(i < j) swap(a[i], a[j]); } if(k <= j) return quick_sort(l, j); return quick_sort(j + 1, r); } int main(){ scanf("%d%d", &n, &k); for(int i = 0; i < n; i ++ ){ scanf("%d", &t); if(!c[t]){ a[len ++ ] = t; c[t] = true; } } k -- ; // k代表索引 k >= len ? puts("NO RESULT") : printf("%d", quick_sort(0, len - 1)); return 0; }
2. 归并排序
#include<bits/stdc++.h> using namespace std; const int N = 1e5 + 10; int a[N], b[N]; void merge_sort(int l, int r){ if(l >= r) return; int mid = l + r >> 1; merge_sort(l, mid), merge_sort(mid + 1, r); int i = l, j = mid + 1, k = l; while(i <= mid && j <= r){ if(a[i] <= a[j]) b[k ++ ] = a[i ++ ]; // 保证稳定性 else b[k ++ ] = a[j ++ ]; } while(i <= mid) b[k ++ ] = a[i ++ ]; while(j <= r) b[k ++ ] = a[j ++ ]; for(i = l; i <= r; i ++ ) a[i] = b[i]; } int main(){ int n; scanf("%d", &n); for(int i = 0; i < n; i ++ ) scanf("%d", &a[i]); merge_sort(0, n - 1); for(int i = 0; i < n; i ++ ) printf("%d ", a[i]); return 0; }
题目一
#include<bits/stdc++.h> using namespace std; typedef long long LL; const int N = 5e5 + 10; int a[N], b[N]; LL res; void merge_sort(int l, int r){ if(l >= r) return; int mid = l + r >> 1; merge_sort(l, mid), merge_sort(mid + 1, r); int i = l, j = mid + 1, k = l; while(i <= mid && j <= r){ if(a[i] <= a[j]) b[k ++ ] = a[i ++ ]; else b[k ++ ] = a[j ++ ], res += mid - i + 1; } while(i <= mid) b[k ++ ] = a[i ++ ]; while(j <= r) b[k ++ ] = a[j ++ ]; for(i = l; i <= r; i ++ ) a[i] = b[i]; } int main(){ int n; scanf("%d", &n); for(int i = 0; i < n; i ++ ) scanf("%d", &a[i]); merge_sort(0, n - 1); printf("%lld", res); return 0; }
3. 堆排序
小根堆
#include<bits/stdc++.h> using namespace std; const int N = 1e6 + 10; int a[N], len; void up(int i){ // 如果父节点不为根节点,且父根节点的值大于子节点,则交换,递归此过程 if(i / 2 && a[i / 2] > a[i]) swap(a[i], a[i / 2]), up(i / 2); } void push(int x){ a[ ++ len] = x; // 压入x至数组结尾 up(len); // 上移 } void down(int i){ int v = i; // 左子节点存在,且左子节点 < 父节点,父节点下移至左子节点 if(i * 2 <= len && a[i * 2] < a[v]) v = i * 2; // 右子节点存在,且右子节点 < 父节点或者左子节点,父节点下移至右子节点 if(i * 2 + 1 <= len && a[i * 2 + 1] < a[v]) v = i * 2 + 1; // 交互 父节点 和 左子节点或者右子节点 if(i != v) swap(a[i], a[v]), down(v); } void pop(){ a[1] = a[len -- ]; down(1); } int peek(){ return a[1]; } int main(){ priority_queue<int, vector<int>, greater<int>> q; const int N = 1e5; for(int i = 0; i < N; i ++ ){ int x = rand(); push(x); q.push(x); } for(int i = 0; i < N / 2; i ++ ){ if(peek() != q.top()){ printf("peel: %d, top: %d\n", peek(), q.top()); return 0; }else{ q.pop(); pop(); } } cout << "end...\n"; return 0; }
大根堆
#include<bits/stdc++.h> using namespace std; const int N = 1e6 + 10; int a[N], len; void up(int i){ // 如果父节点不为根节点,且父根节点的值大于子节点,则交换,递归此过程 if(i / 2 && a[i / 2] < a[i]) swap(a[i], a[i / 2]), up(i / 2); } void push(int x){ a[ ++ len] = x; // 压入x至数组结尾 up(len); // 上移 } void down(int i){ int v = i; // 左子节点存在,且左子节点 < 父节点,父节点下移至左子节点 if(i * 2 <= len && a[i * 2] > a[v]) v = i * 2; // 右子节点存在,且右子节点 < 父节点或者左子节点,父节点下移至右子节点 if(i * 2 + 1 <= len && a[i * 2 + 1] > a[v]) v = i * 2 + 1; // 交互 父节点 和 左子节点或者右子节点 if(i != v) swap(a[i], a[v]), down(v); } void pop(){ a[1] = a[len -- ]; down(1); } int peek(){ return a[1]; } int main(){ priority_queue<int, vector<int>> q; const int N = 1e5; for(int i = 0; i < N; i ++ ){ int x = rand(); push(x); q.push(x); } for(int i = 0; i < N / 2; i ++ ){ if(peek() != q.top()){ printf("peel: %d, top: %d\n", peek(), q.top()); return 0; }else{ q.pop(); pop(); } } cout << "end...\n"; return 0; }
题目一
P3378 【模板】堆
解法1
#include<bits/stdc++.h> using namespace std; const int N = 1e6 + 10; int a[N], len; void up(int i){ // 如果父节点不为根节点,且父根节点的值大于子节点,则交换,递归此过程 if(i / 2 && a[i / 2] > a[i]) swap(a[i], a[i / 2]), up(i / 2); } void push(int x){ a[ ++ len] = x; // 压入x至数组结尾 up(len); // 上移 } void down(int i){ int v = i; // 左子节点存在,且左子节点 < 父节点,父节点下移至左子节点 if(i * 2 <= len && a[i * 2] < a[v]) v = i * 2; // 右子节点存在,且右子节点 < 父节点或者左子节点,父节点下移至右子节点 if(i * 2 + 1 <= len && a[i * 2 + 1] < a[v]) v = i * 2 + 1; // 交互 父节点 和 左子节点或者右子节点 if(i != v) swap(a[i], a[v]), down(v); } void pop(){ a[1] = a[len -- ]; down(1); } int peek(){ return a[1]; } int main(){ int n, op, x; scanf("%d", &n); while(n -- ){ scanf("%d", &op); if(op == 1){ scanf("%d", &x); push(x); }else if(op == 2){ printf("%d\n", peek()); }else{ pop(); } } return 0; }
解法2
#include<bits/stdc++.h> using namespace std; int main(){ priority_queue<int, vector<int>, greater<int>> q; int n, op, x; scanf("%d", &n); while(n -- ){ scanf("%d", &op); switch(op){ case 1: scanf("%d", &x); q.push(x); break; case 2: printf("%d\n", q.top()); break; case 3: q.pop(); break; } } return 0; }
题目二
#include<bits/stdc++.h> using namespace std; const int N = 1e5 + 10; int a[N], len; void up(int i){ // 如果父节点不为根节点,且父根节点的值大于子节点,则交换,递归此过程 if(i / 2 && a[i / 2] > a[i]) swap(a[i], a[i / 2]), up(i / 2); } void push(int x){ a[ ++ len] = x; // 压入x至数组结尾 up(len); // 上移 } void down(int i){ int v = i; // 左子节点存在,且左子节点 < 父节点,父节点下移至左子节点 if(i * 2 <= len && a[i * 2] < a[v]) v = i * 2; // 右子节点存在,且右子节点 < 父节点或者左子节点,父节点下移至右子节点 if(i * 2 + 1 <= len && a[i * 2 + 1] < a[v]) v = i * 2 + 1; // 交互 父节点 和 左子节点或者右子节点 if(i != v) swap(a[i], a[v]), down(v); } void pop(){ a[1] = a[len -- ]; down(1); } int peek(){ return a[1]; } int main(){ int n, x; scanf("%d", &n); for(int i = 0; i < n; i ++ ){ scanf("%d", &x); push(x); } for(int i = 0; i < n; i ++ ){ printf("%d ", peek()), pop(); } return 0; }
思考: 堆排序为什么是不稳定的呢?
普通电子计算机1秒钟的算力大概是8亿也就是
#include <bits/stdc++.h> using namespace std; int main() { int cnt = 0; thread t([&](){ while(true) cnt ++ ; }); t.detach(); // 守护线程 time_t nowtime; time(&nowtime); // 获取1970年1月1日0点0分0秒到现在经过的秒数 tm *p = localtime(&nowtime); // 将秒数转换为本地时间, 年从1900算起, 需要+1900, 月为0-11, 所以要+1 printf("%04d:%02d:%02d %02d:%02d:%02d\n", p->tm_year + 1900, p->tm_mon + 1, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec); this_thread::sleep_for(chrono::seconds(1)); time(&nowtime); p = localtime(&nowtime); printf("%04d:%02d:%02d %02d:%02d:%02d\n", p->tm_year + 1900, p->tm_mon + 1, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec); printf("main: %d\n", cnt); } // Windows平台 #include <bits/stdc++.h> #include <windows.h> using namespace std; int main() { int cnt = 0; thread t([&](){ while(true) cnt ++ ; }); t.detach(); // 守护线程 SYSTEMTIME time; GetLocalTime(&time); printf("%04d/%02d/%02d %02d:%02d:%02d:%03d\n", time.wYear, time.wMonth, time.wDay, time.wHour, time.wMinute, time.wSecond, time.wMilliseconds); this_thread::sleep_for(chrono::seconds(1)); GetLocalTime(&time); printf("%04d/%02d/%02d %02d:%02d:%02d:%03d\n", time.wYear, time.wMonth, time.wDay, time.wHour, time.wMinute, time.wSecond, time.wMilliseconds); printf("main: %d\n", cnt); return 0; } // 789742137
本文作者:爱情丶眨眼而去
本文链接:https://www.cnblogs.com/zshsboke/p/17860786.html
版权声明:本作品采用©️CC BY-NC-SA 4.0许可协议进行许可。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步