1.直接插入排序
算法思想:每趟将一个待排序的元素作为关键字,按照其关键字值的大小插入到已经排好的部分序列的适当位置上,直到插入完成。
最好:O(n-1) 最坏: O(n * n)
平均: O(n * n)
void insertSort(int a[],int n){
int i,j;
int temp;
for(int i=2;i<=n;i++){ //下标从1开始,第一个元素有序,从第二个元素开始处理
temp=a[i];
j=i-1;
while(j>=1&&temp<a[j]){//从待排序之前的元素开始扫描,如果大于待排元素则后移一位。
a[j+1]=a[j];
j--;
}
a[j+1]=temp;
}
}
2.折半插入排序
算法思想:在直接插入排序中,查找插入位置时采用折半查找的方法。
分析:时间复杂度 O(n * n),比直接插入排序减少了比较次数,在记录移动次数方面和直接插入排序是一样的,所以他们的时间复杂度是一样的。
折半插入排序的记录比较次数和初始序列无关。因为每趟排序折半寻找插入位置时,折半次数是一定的(都是在low>high时结束),折半一次就要比较一次,所以比较次数一定。
void BinInsertSort(int a[],int n){
for(i=1;i<n;i++){
low=0;
high=i-1;
while(low<=high){
m=(low+high)/2;
if(a[i]<a[m]) high=m-1;
else low=m+1;
}
//向后移动元素a[high+1...i-1],在a[high+1]处插入a[i]
x=a[i];
for(j=i-1;j>high;j--)
a[j+1]=a[j];
a[high+1]=x;
}
}
3.希尔排序
算法思路:先将待排序列分割成几个子序列,分别进行直接插入排序,基本有序后再对整个序列进行直接插入排序。
说明:希尔排序是不稳定的,时间复杂度O(nlogn)
希尔排序的增量取法要注意:首先增量序列的最后一个值一定是1,其次除1以外的增量序列中的值没有除1以外的公因子(如 8,2,1不可以,8和2有除1以外的公因子2)
void ShellSort(int a[],int n){
dk=n/2;
while(dk>=1){
//一趟希尔排序,对dk个序列分别进行插入排序
for(i=dk;i<n;i++){
x=a[i];
for(j=i-dk;j>=0&&x<a[j];j-=dk)
a[j+dk]=a[j];
a[j+dk]=x;
}
dk/=2;
}
}
4.冒泡排序
算法思想:依次比较相邻元素,逆序则交换,重复n-1次
分析:比较和交换总是发生在相邻元素之间,是稳定的排序算法。时间复杂度O(n * n),空间O(1).
void BubbleSort(int a[],int n){
int i,j,flag;
for(i=n;i>=2;i--){
flag=0;
for(j=2;j<=i;j++){
if(a[j-1]>a[j]) swap(a[j-1],a[j]),flag=1;
}
if(flag==0) return ;
}
}
5.快速排序
算法思想:一趟排序把记录分割成独立的两部分,一部分关键字均比另一部分小,然后再分别对两部分快排。
分析:平均情况下,时间复杂度O(nlogn),记录本来有序时为最坏情况,时间复杂度为O(n*n),当每次的枢纽都把表等分为长度相近的两个子表时,速度是最快的.
int Partition(int a[],int low,int high){
int pivot=a[low];
while(low<high){
while(low<high&&a[high]>=privot) --high;
a[low]=a[high];
while(low<high&&a[low]<=privot) ++low;
a[high]=a[low];
}
a[low]=privot;
return low;
}
void quickSort(int a[],int low,int high){
if(low<=high){
int pivotpos=Partition(a,low,high);
quicksort(a,low,pivotpos-1);
quiclsort(a,privotpos+1,high);
}
}