插入排序
插入排序就是每一步都将一个待排数据按其大小插入到已经排序的数据中的适当位置,直到全部插入完毕。插入排序类似于纸牌玩家整理手中的纸牌过程:每次取一张牌,并在取下一张纸牌之前,将这张纸牌放在合适的位置,使手中的纸牌按顺序排列。
直接插入排序
直接插入排序是最基本的插入排序方法。其基本实现思想如下:
- 首先把第一个元素单独看做一个有序序列,依次将后面的元素逐个与前面有序序列的元素进行比较,找到合适位置插入到该有序序列中;
- 当有序序列扩大为整个原始序列的大小时,排序结束。
/********直接插入排序********/
void Insert_sort(int arr[],int len)
{
int i,j;
int temp;
for(i=1;i<len;i++)//把i=1的数据作为基数,即把第二个数据作为基数;
{
temp=arr[i];//把基数赋给变量temp;
j=i-1;
while(j>=0 && temp<arr[j])
//for(j=i-1;j>=0 && temp<arr[j];j--)//把基数前的数据逐个和基数比较,
{
arr[j+1]=arr[j];
j=j-1;
}
arr[j+1]=temp;
}
}
折半插入排序
折半插入排序(binary insertion sort)是对插入排序算法的一种改进,由于排序算法过程中,就是不断的依次将元素插入前面已排好序的序列中。由于前半部分为已排好序的数列,这样我们不用按顺序依次寻找插入点,可以采用折半查找的方法来加快寻找插入点的速度。
折半插入排序算法是一种稳定的排序算法,比直接插入算法明显减少了关键字之间比较的次数,因此速度比直接插入排序算法快,但记录移动的次数没有变,所以折半插入排序算法的时间复杂度仍然为O(n^2),与直接插入排序算法相同。
/********折半插入排序********/
void BInsert_sort(int arr[],int len)
{
int i,j;
int mid,low,high;
int temp;
for(i=1;i<len;i++)
{
low=0;
high=i-1;
temp=arr[i];
while(low<=high)
{
mid=(low+high)/2;
if(arr[mid]>temp)
high=mid-1;
else
low=mid+1;
}
for(j=i;j>mid;j--)
arr[j]=arr[j-1];
arr[low]=temp;
}
}
希尔排序
希尔排序(Shell Sort)又称为“缩小增量排序”。该方法的基本思想是:先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的,因此希尔排序在时间效率上比前两种方法有较大提高。
希尔排序是基于插入排序的以下两点性质而提出改进方法的:
- 插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率。
- 但插入排序一般来说是低效的, 因为插入排序每次只能将数据移动一位。
/********希尔排序,基于直接插入排序的改进********/
void Sell_sort(int *arr,int len)
{
int step;
int i,j;
int temp;
for(step=len/2; step>0;step/=2) //用来控制步长,最后递减到1
{
// i从第step开始排列,因为插入排序的第一个元素
// 可以先不动,从第二个开始排序
for(i=step;i<len;i++)
{
temp = arr[i];
for(j=i-step;(j>=0 && temp < arr[j]);j-=step)
{
arr[j+step] = arr[j];
}
arr[j+step] = temp; //将第一个位置填上
}
}
}