算法排序(2):插入排序

来源:互联网 发布:mac 照片 导出 编辑:程序博客网 时间:2024/06/05 22:31

插入排序有直接插入排序和希尔排序俩种,我们分别来看:

一、直接插入排序

直接插入排序的原理是将数据分为已排序和待排序俩部分,每次从待排序部分获取一个数据,从已排序的部分找到适合位置插入,直到待排序的数据全部取完。

稳定性:稳定
时间复杂度:最好O(N),平均O(N2), 最坏O(N2)
空间复杂度:O(1)

举个栗子:
需要排序的数据为:4 8 3 6 1
1.先将4作为已经排序部分,8 3 6 1 为待排序部分
2.从待排序部分取出8,插入到已经排序的部分中
3.插入后已排序结果为4 8,整体为 4 8 3 6 1(黑体为已经排好的部分)
4.继续以上操作,取出3插入3 4 8 6 1
5.取出6插入3 4 6 8 1
6.取出1插入1 3 4 6 8
待排序取完数据后,可以得到结果,数据已经全部排好序了。
在插入数据时,为了插入到合适的位置,可能要移动已排好的数据,从而时间复杂度会比较高,也就是说,直接插入排序适合数据量较少,而且比较有序的数据排序。

接下来用代码实现:

void insertsort(int arr[],int len){    int tmp=0;    int j=0;    for(int i=1;i<len;i++)    {        tmp=arr[i];        j=i-1;        while(j>=0&&arr[j]>tmp)        {            arr[j+1]=arr[j];            j--;        }        arr[j+1]=tmp;    }}

二、希尔排序

希尔排序是直接插入排序的升级,用来弥补直接插入排序适合数据量少的缺点。
算法思想是确定一个增量组合,通过增量来划分大数据,每一次划分好数据,对划分的数据分别进行直接插入排序(数据较为无序,但是数据量大大减少),直到最后的增量为一(此时数据已经较为有序),进行最后一次直接插入排序。

稳定性:稳定
时间复杂度:最好O(N),平均O(N1.3), 最坏O(N2)
空间复杂度:O(1)

接下来用代码实现:

void shell(int arr[],int arr_len,int dk)   //一次SHELL{    int tmp,j;    for(int i=dk;i<arr_len;i++)    {        tmp=arr[i];        j=i-dk;        while(j>=0&&arr[j]>tmp)        {            arr[j+dk]=arr[j];            j-=dk;        }        arr[j+dk]=tmp;    }}void shellsort(int arr[],int arr_len,int dka[],int dka_len)    //希尔排序总控制{    for(int i=0;i<dka_len ;i++)    {        shell(arr,arr_len,dka[i]);    }}

由于希尔排序不稳定,我们来做一点修改,让它变得稳定。我的一个简单思路是,首先将待排序数组预处理,将重复的数据筛选出来,直到无重复数据部分进行最后一次希尔排序,重复数据参与这最后一次希尔排序,即转化为一次直接插入排序,我们知道直接插入排序是稳定的,所以本次希尔排序也稳定。

代码如下:

int init(int arr[],int arr_len,int *brr,int *crr){    int i=1;    int j=1;    int k=0;    int key=0;    brr[0]=arr[0];    for(i;i<arr_len ;i++)    {        key=k;        for(int p=0;p<j;p++)        {            if(brr[p]==arr[i])            {                crr[k]=arr[i];                k++;                break;            }        }        if(key==k)        {            brr[j]=arr[i];            j++;        }    }    return k;}void shell(int arr[],int arr_len,int dk){    int tmp,j;    for(int i=dk;i<arr_len;i++)    {        tmp=arr[i];        j=i-dk;        while(j>=0&&arr[j]>tmp)        {            arr[j+dk]=arr[j];            j-=dk;        }        arr[j+dk]=tmp;    }}void show(int arr[],int len){    for(int i=0;i<len;i++)    {        printf("%d ",arr[i]);    }    printf("\n");}void shellsort(int arr[],int arr_len,int dka[],int dka_len,int *brr,int *crr){    int crrlen=init(arr,arr_len,brr,crr);    for(int i=0;i<dka_len-1 ;i++)    {        shell(brr,arr_len-crrlen,dka[i]);    }    int j=0;    for(j;j<arr_len-crrlen;j++)    {        arr[j]=brr[j];    }    for(int k=0;k<crrlen;k++)    {        arr[j]=crr[k];        j++;    }    show(arr,arr_len);    shell(arr,arr_len,1);}
原创粉丝点击