直接插入排序
直接插入排序的思想是,一开始将整个数据表看成是由一个仅有一个元素的有序表和含有n-1个元素的无序表组成,每次从无序表中选一个元素插入到有序表中的合适位置,一般情况下取原数组第一位元素作为初始的有序表。插入操作的具体做法是,在向有序表某个位置添加元素时,该位置及之后的元素先后移空出一个位置,而后将待插元素放到那个位置去。
void insert_sort(int *R,int n){
int i,j;
for(i=1;i<n;i++){
int tmp=R[i];
for(j=i;j>0&&R[j-1]>tmp;j--){
R[j]=R[j-1];
}
R[j]=tmp;
}
}
此算法的平均时间效率为O(N2),最优时间效率及对已排好序的数组操作的效率是O(N)。
以下分别是对随机生成的1000、10000、100000个随机数排序后的结果及时间统计,可见数据量增加十倍,耗时就增加百倍左右
二分插入排序
希尔排序
希尔排序又叫缩小增量排序,它是直接插入排序的一种改进,其基本思想是,选取某一增量(增量的选取对于希尔排序的效率很重要),在具有相同增量的序列中进行直接插入排序,然后将增量缩小,继续排序直至增量为1的情形下排序结束,则可以得到已经排好序的序列。由于直接插入排序对于小型数组而言效率还是挺高的,所以希尔排序综合而言效率要比直接插入排序要高。
void shell_sort(int *R,int n){
int i,j,increment;
for(increment=n/2;increment>0;increment/=2){
for(i=increment;i<n;i++){
int tmp=R[i];
for(j=i;j>=increment;j-=increment){
if(tmp<R[j-increment]){
R[j]=R[j-increment];
}else{
break;
}
}
R[j]=tmp;
}
}
}
选择排序
冒泡排序
void bubble_sort(int *R,int n){
bool flag=true;
for(int i=1;i<n;i++){
flag=false;
for(int j=n-1;j>=i;j--) {
if (R[j - 1] > R[j]) {
int tmp = R[j];
R[j] = R[j - 1];
R[j - 1] = tmp;
flag = true;
if (flag == false) {
continue;
}
}
}
}
}
快速排序
快速排序是传说中目前最快的排序,其基本思想是,每次选择一个枢纽值,将序列分成两个子序列,两个子序列中的元素分别都大于枢纽值或都小于或等于枢纽值,然后对子序列进行快排,即经典的D&C思想加递归,最终返回的序列就是排序好的序列。
基于这个思想,枢纽值的选取对算法的效率影响很大,这也是快排不太稳定的原因。通常的简单的取法就是以每一轮的第一个元素作为枢纽值,但这种做法对于所输入的已经预排序好的数组而言效率极低(枢纽值以外的元素要么都在这个子序列要么都在另一个里)。所以,可以考虑随机选取枢纽值。但使用随机数生成器代价昂贵,所以还可以考虑...大佬给出的三数中值分割法,安全地消除预排序输入的坏情形。
void quicksort(int *R,int left, int right){
//选第一个元素作为枢纽值,这通常不太好
int i=left,j=right;
int tmp = R[left];
while(i<j){
while(R[j]>tmp&&j>i){
j--;
}if(j>i){
R[i]=R[j];
i++;
}
while(R[i]<=tmp&&i<j){
i++;
}if(j>i){
R[j]=R[i];
j--;
}
R[i]=tmp;
if(left<i-1){
quicksort(R,left,i-1);
}if(i+1<right){
quicksort(R,i+1,right);
}
}
}