插入排序
就是相当于打扑克,不断把一个数插入到之前已经已经有序的序列中去
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010;
int n;
int a[N];
void insert_sort()
{
for(int i=1;i<n;i++){
int t = a[i];
int j = i;
while(j > 0 && a[j-1] > t) //j是枚举的要插入的位置
{
a[j] = a[j-1];
j--;
}
a[j] = t;
}
}
int main()
{
cin >> n;
for(int i=0;i<n;i++) cin >> a[i];
insert_sort();
for(int i=0;i<n;i++) cout << a[i] << " ";
return 0;
}
最好情况: O(n)
平均情况: O(n^2)
最坏情况: O(n^2)
辅助空间: O(1) 只需要开一些变量就好了
折半插入排序
就是在直接插入排序上做了个优化,直接插入排序是当要插入一个数时从后向前一个一个比较然后来找到位置进行插入,折半插入是在比较是采用二分查找的方式减少了比较次数,但是移动次数是无法优化的
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010;
int n;
int a[N];
void binary_search_sort()
{
for(int i=1;i<n;i++)
{
//如果插入的数最终是会插入到最右端的话用二分搜索效率反而不高所以需要特判掉这种情况
if(a[i] > a[i-1]) continue;
int l = 0, r = i - 1, num = a[i];
while(l < r)
{
int mid = (l+r)/2;
if(a[mid] > num) r = mid;
else l = mid + 1;
}
//此时r的位置就是这个数应该插入的位置
for(int j=i-1;j>=r;j--) a[j+1] = a[j];
a[r] = num;
}
}
int main()
{
cin >> n;
for(int i=0;i<n;i++) cin >> a[i];
binary_search_sort();
for(int i=0;i<n;i++) cout << a[i] << " ";
return 0;
}
平均情况下时间复杂度为O(n^2)
因为尽管查找次数下降了,但是移动次数是没变的,瓶颈在移动次数上
冒泡排序
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010;
int n;
int a[N];
void bubble_sort()
{
for(int i=0;i<n-1;i++) //0~i-1位置是排好序的,现在要确定i号位置的元素
{
bool if_swap = false; //如果某一趟从后向前遍历发现都没有交换元素说明整个序列都有序了可以直接退出
for(int j=n-1;j>i;j--)
{
if(a[j] < a[j-1]){
swap(a[j],a[j-1]);
if_swap = true;
}
}
if(!if_swap) break;
}
}
int main()
{
cin >> n;
for(int i=0;i<n;i++) cin >> a[i];
bubble_sort();
for(int i=0;i<n;i++) cout << a[i] << " ";
return 0;
}
简单选择排序
就是每次选择最小的元素换到对应位置上,和冒泡的思想差不多
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010;
int n;
int a[N];
void select_sort()
{
for(int i=0;i<n;i++)
{
int k = i;
for(int j=i+1;j<n;j++){
if(a[j] < a[i]) k = j;
}
swap(a[i],a[k]);
}
}
int main()
{
cin >> n;
for(int i=0;i<n;i++) cin >> a[i];
select_sort();
for(int i=0;i<n;i++) cout << a[i] << " ";
return 0;
}
希尔排序
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010;
int n;
int a[N];
void shell_sort()
{
for(int d=n/2;d>=1;d/=2)
{//先枚举公差
for(int start=0;start<d;start++)//枚举每一组
{
for(int i=start+d;i<n;i+=d) //每一组内使用插入排序
{
int t = a[i], j = i;
while(j > start && a[j-d] > t){
a[j] = a[j-d];
j -= d;
}
a[j] = t;
}
}
}
}
int main()
{
cin >> n;
for(int i=0;i<n;i++) cin >> a[i];
shell_sort();
for(int i=0;i<n;i++) cout << a[i] << " ";
return 0;
}
快速排序
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010;
int n;
int a[N];
void quick_sort(int a[],int l,int r)
{
if(l>=r) return; //如果子问题中只有一个数那么就不需要再排了
int i=l-1,j=r+1,x=a[l+r>>1];
while(i<j)
{
do{i++;}while(a[i]<x); //这里必须先i++再判断while条件
//因为如果这里不先i++那么当右边换过来个<=x的数到左边,结果这个数刚好等于x那么就死循环了
do{j--;}while(a[j]>x);
if(i<j) swap(a[i],a[j]); //这里必须判断i<j,因为最终时i=j+1,不判断这个条件会把本来正确的a[i],a[j]这两个数再换错一次
}
quick_sort(a,l,j);
quick_sort(a,j+1,r);
}
int main()
{
cin >> n;
for(int i=0;i<n;i++) cin >> a[i];
quick_sort(a,0,n-1);
for(int i=0;i<n;i++) cout << a[i] << " ";
return 0;
}
堆排序
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010;
int n;
int heap[N],heap_size; //size是堆的规模
//down是建堆过程
void down(int u)
{
int t = u;
if(2*u<=heap_size && heap[2*u] > heap[t]) t = 2*u;
if((2*u+1)<=heap_size && heap[2*u+1] > heap[t]) t = 2*u+1;
if(t!=u)
{
swap(heap[t],heap[u]);
down(t);
}
}
int main()
{
cin >> n;
heap_size = n;
for(int i=1;i<=n;i++) cin >> heap[i];
//堆排序过程
//建堆
for(int i=n/2;i>=1;i--) down(i);
//堆排序过程,每次把heap[1]的元素放到堆尾,然后只要n-1次就可以
for(int i=0;i<n-1;i++){
swap(heap[1],heap[heap_size]);
heap_size--;
down(1);
}
for(int i=1;i<=n;i++) cout << heap[i] << " ";
return 0;
}
归并排序
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010;
int n;
int a[N],w[N];
void merge_sort(int l,int r)
{
if(l>=r) return;
int mid = (l+r)/2;
merge_sort(l,mid);
merge_sort(mid+1,r);
int i = l, j = mid+1, k = 0;
while(i<=mid && j<=r)
{
if(a[i]<=a[j]) w[k++] = a[i++];
else w[k++] = a[j++];
}
while(i<=mid) w[k++] = a[i++];
while(j<=r) w[k++] = a[j++];
for(int i=l,j=0;j<k;j++,i++) a[i] = w[j]; //记得把辅助数组中的结果写回
}
int main()
{
cin >> n;
for(int i=0;i<n;i++) cin >> a[i];
merge_sort(0,n-1);
for(int i=0;i<n;i++) cout << w[i] << " ";
return 0;
}