希尔排序

来源:互联网 发布:华晨中华v5配置数据图 编辑:程序博客网 时间:2024/06/05 16:46

【0】README

0.1) 本文总结于 数据结构与算法分析,但源代码均为原创;旨在理清希尔排序的具体步骤;


【1】希尔排序相关

1.1)希尔排序(shellsort)的由来: 它的名称源于它的发明者 Donald Shell, 该算法是冲破二次时间屏障的第一批算法之一;
1.2)工作原理:它通过比较相距一定间隔的元素来工作, 各趟比较所用的距离随着算法的进行而减小,直到只比较相邻元素的最后一趟排序为止, 由于这个原因, 希尔排序有时也叫做 缩小增量排序;
1.3)增量序列:希尔排序使用一个序列 h1、h2、……、ht, 叫做增量序列; 只要h1=1 , 任何增量都是可行的;重点是, 有些增量序列比另外一些增量序列更好;
1.4)在使用增量hk 的一趟排序后,对于每一个 i , 我们有A[i] <= A[i+hk]; 所以相隔 增量hk 的元素都被排序, 此时称文件是 hk-排序的;
1.5)hk-排序的一般做法是(用到了插入排序): 对于 hk, hk+1, hk+2,……,N-1中的每一个位置i, 把其上的元素放到 i,i-hk, i-2hk…..中间的正确位置上;虽然这不是最终结果,但是结果考察,我们发现,一趟hk-排序的作用就是对 hk个独立的 子数组执行一次插入排序


【2】增量序列的选择建议:

2.0)希尔增量的问题在于: 这些增量对 未必互为素数, 因此较小的增量可能影响很小;
2.1)推荐(本源代码也使用的这种增量序列): Hibbard 提出一个稍微不同的增量序列, 它在实践中给出更好的结果, 增量形如1, 3, 7, ……, 2^k - 1(如, N=15, 则 int k=log15 = 3, 2, 1 也即增量序列 7, 3, 1);
2.2)希尔增量序列的选择: 其余的增量序列还有Hibbard:{1, 3, …, 2^k-1},Sedgewick(推荐):{1, 5, 19, 41, 109…}该序列中的项或者是9*4^i - 9*2^i + 1或者是 4^i - 3*2^i + 1。使用不同的增量对希尔排序的时间复杂度的改进将不一样,甚至一点小的改变都将引起算法性能剧烈的改 变。(在实践中: 堆排序慢于 使用 Sedgewick 增量序列的希尔排序;)
2.3)增量序列的一种流行(但是不好)的选择是使用 shell 建议的序列:这里写图片描述
定理: 使用 Hibbard 增量的希尔排序的最坏情况运行时间为 这里写图片描述
2.4)希尔排序的具体步骤(步骤):
这里写图片描述


【3】源代码+打印结果

3.1)download source code :
https://github.com/pacosonTang/dataStructure-algorithmAnalysis/blob/master/chapter7/p168_shellSort.c
3.2)source code at a glance :

#include <stdio.h>#include <math.h>// 计算 log 以2为底的对数double log2(double input){       return log(input) / log(2); }// we adopt ascending order to execute shellSorting operationvoid shellSort(int data[], int size){    int temp;    int round;    int index;    int i;    int offset;    round = (int)log2(size);        for(; round > 0;)     {        offset = (int)pow(2, round) - 1; // assignment of offset, like 7, 3, 1              for(i = offset; i < size; i++) // i like 7, 8, 9, ...., size-1         {                               temp = data[i];// the idea refers to the insertion sort                         for(index = i; index >= offset; index -= offset)                                    if(temp < data[index - offset])                                 data[index] = data[index - offset];                else                    break;                      data[index] = temp;        }        round --;    }}void printArray(int data[], int size){    int i;    for(i = 0; i < size; i++)        printf("%5d", data[i]);    printf("\n");}int main(){     int size;    int data[] = {100, 1000, 100, 10, 6, 2, 19, 25, 15, 55, 35, 5, 110, 120, 119};    size = 15;    printf("\n=== before executing shellSort ===\n");    printArray(data, size);    shellSort(data, size);    printf("\n=== after executing shellSort ===\n");    printArray(data, size);     return 0;}

3.3)打印结果:
这里写图片描述

0 0