复习一下插入排序、冒泡排序、希尔排序、堆排序、计数排序、基数排序
插入排序 平均复杂度 O(n^2),最好情况为O(N),且是稳定的。
插入排序是在一个已经有序的小序列的基础上,一次插入一个元素。当然,刚开始这个有序的小序列只有1个元素,也就是第一个元素(默认它有序)。
冒泡排序 平均复杂度 O(n^2),最好情况为O(N),且是稳定的。
它从左到右依次交换元素,若在一次循环中没有出现交换情况,则表明有序,则可停止程序。
对于大规模的数组,插入排序很慢,因为它只能交换相邻的元素,每次只能将逆序数量减少 1。
希尔排序的出现就是为了解决插入排序的这种局限性,它通过交换不相邻的元素,每次可以将逆序数量减少大于 1。
希尔排序使用插入排序对间隔 h 的序列进行排序。通过不断减小 h,最后令 h=1,就可以使得整个数组是有序的。
一个堆的高度为 logN,因此在堆中插入元素和删除最大元素的复杂度都为 logN。
对于堆排序,由于要对 N 个节点进行下沉操作,因此复杂度为 NlogN。
堆排序时一种原地排序,没有利用额外的空间。
计数排序假设输入元素的范围落在一个区间[0,k),运行时间是O(n+k),他是稳定的。
基数排序是先按照最低位进行排序来解决卡片排序问题(将整数按位数切割成不同的数字,然后按每个位数分别比较),同样他是稳定的,其中按位排序可退化为落在范围为0-9的计数排序。
#include<stdlib.h>
#include<stdio.h>
#define leftChild(i) (2*(i)+1)
static void swap(int *a,int *b){
int tmp;
tmp=*a;
*a=*b;
*b=tmp;
}
void insertSort(int A[],int N){
int i,j;
for(i=1;i<N;i++){
int tmp=A[i];
for(j=i;j>0 && tmp<A[j-1];j--)
A[j]=A[j-1];
A[j]=tmp;
}
}
void shellSort(int A[],int N){
int increase,i,j,tmp;
for(increase=N/2;increase>0;increase/=2){
for(i=increase;i<N;i++){
tmp=A[i];
for(j=i;j>=increase;j-=increase){
if(tmp<A[j-increase])
A[j]=A[j-increase];
else break;
}
A[j]=tmp;
}
}
}
void printArray(int arr[],int N){
int i;
for(i=0;i<N;i++)
printf("%d\t",arr[i]);
printf("\n");
}
static void percDown(int arr[],int pos,int N){
int child,i;
int tmp=arr[pos];
for(i=pos;leftChild(i)<N;i=child){
child=leftChild(i);
if(child!=N-1 && arr[child]<arr[child+1])
++child;
if(tmp<arr[child])
arr[i]=arr[child];
else break;
}
arr[i]=tmp;
}
void heapSort(int arr[],int N){
int i;
for(i=N/2;i>=0;i--)
percDown(arr,i,N);
for(i=N-1;i>0;i--){
swap(&arr[0],&arr[i]);
percDown(arr,0,i);
}
}
void bubbleSort(vector<int>&v){
if(v.empty())return;
auto n=v.size();
for(int i=n-1;i>=0;--i){
bool flag=true;
for(int j=0;j<i;++j){
if(v[j]>v[j+1]){
swap(v[j],v[j+1]);
flag=false;
}
}
if(flag)return;
}
int main(){
int array[9]={56,78,33,22,14,156,123,64,634};
insertSort(array,9);
printArray(array,9);
shellSort(array,9);
printArray(array,9);
heapSort(array,9);
printArray(array,9);
return 0;
}
以下为计数排序和基数排序的实现:
#include<iostream>
#include<vector>
using namespace std;
vector<int> countingSort(const vector<int>&a,vector<int>&b){
auto res=a;
for(int i=0;i!=a.size();++i){
++b[a[i]];
}
for(int i=1;i!=b.size();++i)
b[i]+=b[i-1];
for(int i=a.size()-1;i>=0;--i){
res[b[a[i]]-1]=a[i];
--b[a[i]];
}
return res;
}
int get_max(const vector<int>&v){
auto ret=v[0];
for(int i=1;i<v.size();++i)
ret=max(ret,v[i]);
return ret;
}
void count_sort(vector<int>&v,int f){
vector<int>tmp(10);
vector<int>ret=v;
auto n=v.size();
for(int i=0;i<n;++i)
++tmp[(v[i]/f)%10];
for(int i=1;i<10;++i)
tmp[i]+=tmp[i-1];
for(int i=n-1;i>=0;--i){
ret[tmp[(v[i]/f)%10]-1]=v[i];
--tmp[(v[i]/f)%10];
}
for(int i=0;i<n;++i)
v[i]=ret[i];
}
void radix_sort(vector<int>&v){
if(v.size()<2)return;
auto max=get_max(v);
for(int i=1;max/i>0;i*=10){
count_sort(v,i);
}
}
int main(){
/*
vector<int>a{2,5,3,0,2,3,0,3};
vector<int>b(6);
auto res=countingSort(a,b);
for(auto i:res)cout<<i<<",";
cout<<endl;
*/
vector<int>a{53, 3, 542, 748, 14, 214, 154, 63, 616};
radix_sort(a);
for(auto i:a)cout<<i<<",";
cout<<endl;
}