希尔排序详解

来源:互联网 发布:淘宝运动鞋 编辑:程序博客网 时间:2024/06/05 19:09


基本概念:

希尔排序按其设计者希尔(Donald Shell)的名字命名,它是一种基于插入排序的快速排序算法,要了解希尔排序,必须先掌握插入排序的原理与实现


希尔排序通过将比较的全部元素分为几个区域来提升插入排序的性能。这样可以让一个元素可以一次性地朝最终位置前进一大步。然后算法再取越来越小的步长进行排序,算法的最后一步就是普通的插入排序,但是到了这步,需排序的数据几乎是已排好的了(此时插入排序较快)。


步长的选择是希尔排序的重要部分。只要最终步长为1任何步长序列都可以工作(且步长要小于数组长度)。算法最开始以一定的步长进行排序。然后会继续以一定步长进行排序,最终算法以步长为1进行排序。当步长为1时,算法变为插入排序,这就保证了数据一定会被排序。


关于希尔排序的时间复杂度,与步长息息相关:



过程如图:



简单例子分析:

待排序数组:
{6, 5, 3, 1, 8, 7, 2, 4, 9, 0}

第一次步长h=4,
那么数组按照步长可以拆分成4个小数组([0]6的意思是下标[0]的值为6)

{[0]6, [4]8, [8]9}
{[1]5, [5]7, [9]0}
{[2]3, [6]2}
{[3]1, [7]4}

对这4个小数组分别进行插入排序后,4个小数组变成:
{[0]6, [4]8, [8]9}
{[1]0, [5]5, [9]7}
{[2]2, [6]3}
{[3]1, [7]4}
合并起来就是:{6, 0, 2, 1, 8, 5, 3, 4, 9, 7}

第二次步长h=1,
那么数组按照步长只有1个数组了
{6, 0, 2, 1, 8, 5, 3, 4, 9, 7}

对这个数组进行一次插入排序后,最终顺序就成为:
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}


源码:

#include <stdio.h>void shell_sort(int arr[], int size){    if (arr == NULL)        return ;    int h = 1; /* 关于步长,取值没有统一标准,必须小于size,最后一次步长要为1 */        /* 计算首次步长 */    while (h < size/3)        h = 3*h + 1;    int i, j, temp;    while (h >= 1) {        for (i = h; i < size; ++i) {            /* 将a[i]插入到a[i-h]、a[i-2h]、a[i-3h]...中 */             for (j = i; j >= h && (arr[j] < arr[j-h]); j -= h) {                temp = arr[j];                arr[j] = arr[j-h];                arr[j-h] = temp;            }        }        /* 每轮内循环后输出数组的现状 */        int k;        printf("the step=%d : ", h);        for (k = 0; k < size; ++k) {            printf("%d ", arr[k]);        }        printf("\n");        /* 计算下一轮步长 */        h = h / 3;    }}int main(){    int arr[] = {6, 5, 3, 1, 8, 7, 2, 4, 9, 0};    int size = sizeof(arr) / sizeof(int);    //sort    shell_sort(arr, size);    //print    int i = 0;    for (i; i < size; ++i) {        printf("%d\n", arr[i]);    }    return 0;}

编译运行:



原文出自:http://blog.csdn.net/daiyudong2020/article/details/52445044



End;

0 0
原创粉丝点击