插入排序
直接插入排序
(递增排序)将1-n个数值看成是有序的,从n+1(用临时变量保留)开始一次往前比较,若比当前值小,则当前值向后移;否则则插入该位置;从n+2个元素以后一次进行此操作。
for(i=1;i<n;i++){ //从第二个元素开始,将第一个默认为有序
if(a[i]<a[i-1]){
temp = a[i]; //保存临时变量
for(j=i-1; temp<a[j]; j--){
a[j+1] = a[j]; //后移
}
a[j+1] = temp;
}
}
希尔排序
直接插入算法在数据较小或者基本有序的情况下比较好用,但较差的一些情况下时间复杂度达到n的平方(既有移动次数又有比较次数);而希尔排序是利用分组的形式将数组数量缩小,这样可以使得直接排序起到很好的效果。
for(dk=n/2; dk>=1; dk=dk/2){ //必须先进行分组一般是二分
for(i=dk; i<n; i++){//也是从第二个元素开始
if(a[i]<a[i-dk]){
temp = a[i];
for(j=i-dk; j>=0&&temp<=a[j]; j-=dk){
a[j+dk] = a[j];
}
a[j+dk] = temp;
}
}
}
折半查找排序
问题的关键在于查找的过程,因为直接插入排序是依次一个一个的比较,折半查找优点在于缩短查找的时间。直接确定需要查找的中间值
从第二个值开始然后直接去确定前面有序的中间值,与之比较然后前移或者后移确定
for(i=1; i<n; i++){
temp = a[i];
low = 0; high = i-1;
while(low<=high){ //low大于high时,high+1的值即应该放的位置
mid = (low+high)/2;
if(temp<a[mid])
high = mid-1;
else
low = mid+1;
}
for(j=i-1; j>=high+1; j--){
a[j+1] = a[j];
}
a[high+1] = temp;
}
交换排序
冒泡排序
根据所属类型可知其排序过程是交换(c中运用地址,c++中运用引用),从第一个元素开始,从后向前交换,每次将一个元素放在最终位置上,(例如第一遍交换完,最小的元素一定放在第一位)
for(i=0; i<n; i++){
for(j=n-1; j>=i;j--){ /*即使发生交换,也会继续进行直到前i个元素已经有序为之,不过这里应该有一个控制变量表示是否发生交换如果未发生交换表示所有元素已经在应有之位,即使i还没有走完也可以停止了*/
if(a[j]<a[j-1])
swap(a[j], a[j-1]);
}
}
快速排序
一开始较难立即,后来在知乎上看到有人将快排比喻为挖坑很形象也易于理解。即用基值将序列分为两段,且每次排序后基值都处在正确的位置。分为两个函数,快排函数和分部函数。
void Quicksort(int a[], int low, int high){//递归
if(low<high){
int index = Partion(a, low, high);//调用分部函数分区
Quicksort(a, low, index-1);
Quicksort(a, index+1, high);
}
}
int Partion(int a[], int low, int high){
int index = a[low];//一般讲序列的第一个数作为基值,此时low出为坑
while(low<high){
while(low<high&&a[high]>=index) --high; //寻找比基值小的数填low坑
a[low] = a[high];
while(low<high&&a[low]<=index) ++low;//寻找比基值大的数填high坑
a[high] = a[low];
}
a[high] = index;//基值归位
return high; //返回基值,且将以此值左右分部分别进行排序
}
选择排序
主要是从后向前选出最小值,保存其地址然后从前向后依次填充
void selecsort(int a[], int n){
int i, j, temp, min;
for(i=0; i<n; i++){
min = i;
for(j=n-1; j>=i;j--){
if(a[min]>=a[j])
min = j; //保存地址
}
swap(a[min],a[i]); //此处c与c++传值可以有不同
}
}