排序-->插入排序(直接插入排序&&希尔排序)

来源:互联网 发布:spss数据分析师认证 编辑:程序博客网 时间:2024/05/29 03:09

写在前面

博客的全部代码以及测试用例全部已上传GitHub:直接插入排序&&希尔排序

直接排序

直接排序其实就是一次将无序空间向有序空间转换的过程,其实所有排序都是这样,只不过,在直接排序中,我们是将原本的数据内容分为了前后两个空间,前面的一个空间是有序的,而后面的空间无序,我要做的就是慢慢的将有序空间增长,将无序空间缩小,直到无序空间为0,我们就可以得到一个有序的数据链;这里写图片描述
在上图中,我们大致可以观察出这套算法所运行的过程:

  1. 在原始数组中,默认第一个数字是有序的,其他后面的数字全部无序;
  2. 在无序的数字中,从前向后开始,取第一个数字与有序区域的数字从后向前比较;
  3. 如果有序中的数字大于该数字,就将大于的数字向后移一位;
  4. 直到遇到一个小于或者等于它的数字,就讲该数字插入到当前位置;
  5. 直到全部有序,否则就重复2-4的步骤;
//version1 时间复杂度O(N^2)void InsertSort(int *array, size_t size){    for (size_t idx = 1; idx < size; ++idx)    {        int end = idx - 1;        int key = array[idx];        while (end >= 0 && (key < array[end]))        {            array[end + 1] = array[end];            --end;        }        array[end + 1] = key;    }}

我们可以看到,在上面的代码中,确实比较简单,到那时事件复杂度达到了O(N^2);其实,我们可以在这个代码中找到一些,我们原来学习到的东西,替换它,比如在有序空间中找数字时,可以用到二分查找;

//version2 时间复杂度降低,利用二分查找来找位置void InsertSort_OP(int *array, size_t size){    for (size_t idx = 1; idx < size; ++idx)    {        int end = idx - 1;        int left = 0;        int right = idx;        int key = array[idx];        while (left <= right)        {            int mid = left + ((right - left) >> 1);            if (key < array[mid])                right = mid - 1;            else                left = mid + 1;        }        while (end >= left)        {            array[end + 1] = array[end];            --end;        }        array[end + 1] = key;    }}

希尔排序

从根本意义上来讲,希尔排序其实就是直接插入排序的一个改良版,希尔排序的速度要远胜于直接插入排序;
这里写图片描述

从图中可以看到:
1. 我们将原始数据分割按照某个个数分割为几个分组;
2. 然后一直按照默认的大小一直分割下去,知道只有一个元素时停止(前面如果按照规定的元素个数来划分有剩余的话就轮空);
3. 然后从下向上一次排序;知道数组全部有序;
4. 其中,我在画图的时候只是随意的切割方法,其实在很多前辈做了大量的测试后发现,当gap = gap/3+1;时是效率最高的;

//希尔排序  时间复杂度在N^1.25~1.6N^1.25void ShellSort(int *array, size_t size){    int gap = size;    while (gap > 1)    {        gap = gap / 3 + 1;        for (size_t idx = gap; idx < size; ++idx)        {            int end = idx - gap;            int key = array[idx];            while (end >= 0 && (key < array[end]))            {                array[end + gap] = array[end];                end -= gap;            }            array[end + gap] = key;        }    }}
原创粉丝点击