基础算法-排序
自嗨产物,图片来自csdn,侵删
1.冒泡排序
时间复杂度O(n²) 空间复杂度O(1)(临时变量)
步骤:比较相邻元素。每次操作都使本轮最大(小)元素位于队列最后(前)。
#include<bits/stdc++.h> //洛谷p1177,TLE using namespace std; #define N 100001 int n,a[N]; int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<n;i++) for(int j=n;j>i;j--) if(a[j]<a[j-1]) swap(a[j],a[j-1]); for(int i=1;i<=n;i++) printf("%d ",a[i]); }
两种优化思路:1. 标志位 2. 鸡尾酒排序(需要判断排序是否完成)
最坏情况复杂度不变。
2.选择排序
时间复杂度O(n²) 空间复杂度O(1)
步骤:找到最小(大元素)放在相应位置。(和首末元素交换位置)
#include<bits/stdc++.h> //洛谷p1177,TLE using namespace std; #define N 100001 int n,a[N]; int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); int temp; for(int i=1;i<n;i++){ temp=i; for(int j=i+1;j<=n;j++) if(a[temp]>a[j]) temp=j; swap(a[temp],a[i]); } for(int i=1;i<=n;i++) printf("%d ",a[i]); }
3.插入排序
时间复杂度O(n²) 空间复杂度O(1)
步骤:从第一个元素开始,将元素插入已排序完成部分的合适位置。(有点像单个元素的冒泡?)
#include<bits/stdc++.h> //洛谷p1177,TLE using namespace std; //为什么别的都TLE四个这个只有两个? #define N 100001 int n,a[N]; int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=2;i<=n;i++) for(int j=i;j>1;j--){ if(a[j]>=a[j-1])break; swap(a[j],a[j-1]); } for(int i=1;i<=n;i++) printf("%d ",a[i]); }
4.希尔排序(递减增量排序)
插入排序的改进算法
理论:插入排序在队列比较有序时效率更高
步骤:将原序列(穿插)分为多个子序列,分别对每个子序列进行插入排序,逐渐增大序列,最后对整个序列进行插入排序。
复杂度证明、合理增量数量、代码暂略
5.归并排序
时间复杂度O(nlogn) 空间复杂度
步骤:分治、合并
#include<bits/stdc++.h> //P1177AC using namespace std; #define N 100001 int n,a[N]; void functionsort(int n,int t){//要排序n个元素,第一个下标为t if(n==1) return; functionsort(n/2,t); functionsort(n/2+n%2,t+n/2); //注意编号 int temp[N+1],tema=t,temb=t+n/2; //temp[n+1]可行 for(int i=t;i<n+t-1;i++){ //把所有i减去(t-1)(未调) if(a[tema]>a[temb])temp[i]=a[temb],temb++; else temp[i]=a[tema],tema++; if(tema==t+n/2){ for(int j=i+1;j<=n+t-1;j++)temp[j]=a[temb],temb++; break; } if(temb==t+n){ for(int j=i+1;j<=n+t-1;j++)temp[j]=a[tema],tema++; break; } } for(int i=t;i<n+t;i++) a[i]=temp[i]; return; } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); functionsort(n,1); for(int i=1;i<=n;i++) printf("%d ",a[i]); }
6、快速排序
写的全是问题,别看
#include<bits/stdc++.h>//TLE三个点,不知道是不是因为最坏情况的O(n2)复杂度 using namespace std; #define N 100001 int a[N],n; void function_sort(int left,int right){ int cleft=left,cright=right; if(left==right) return; if(left+1==right){ if(a[left]>a[right]) swap(a[left],a[right]); return; } int key=left,tem=a[left]; while(left!=right){ //既然平均复杂度O(n log n),自然每次循环达到O(n) while(right>left&&a[right]>=tem) right--; //其实是很优美的写法,但是要注意的点太多了 while(left<right&&a[left]<=tem) left++; if(left<right) swap(a[left],a[right]); } swap(a[cleft],a[left]),key=left; if(key>cleft) function_sort(cleft,key-1); if(key<cright) function_sort(key+1,cright); return; } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); function_sort(1,n); for(int i=1;i<=n;i++) printf("%d ",a[i]); }