常用排序算法之希尔排序

希尔排序

希尔排序并不能见名知意,因为希尔排序的名称起源于它的发明者Donald Shell。

  • 基本思想:

     希尔排序是每次比较相邻一定间隔的元素(而每次需要相邻多少个元素进行比较,是由一个增量序列来决定的。因此,希尔排序有时也叫做缩小增量排序),直到只比较相邻元素的最后一趟排序为止。因此使用希尔排序时,每趟排序先将所有元素按某个增量d分成若干组子序列,对每个子序列进行排序。

增量序列h1,h2,…..ht ,只要h1=1,任何增量序列都是可以的,但是有些增量序列 会比另外的增量序列要更好。

数组A  

A[0]

A[1]

A[2]

A[3]

A[4]

A[5]

A[6]

A[7]

A[8]

A[9]

A[10]

A[11]

A[12]


初始


 81 

94

 11 

96

12

35 

17

95

28

58

41

75

15

Inc=6排序后

15

94 11 58 12 35 17 95 28 96 41 75 81

Inc=3排序后

15

12 11 17 41 28 58 94 35 81 95 75 96

Inc=1排序后

11

12

15

17

28

35

41

58

75

81

94

95

96

  • 原理分析:

 如图所示,初始增量为6,将数组A中相邻间隔为6的元素进行比较。

 因此:

A[0]、A[6]进行比较

A[1]、A[7]进行比较

A[2]、A[8]进行比较

A[3]、A[9]进行比较

A[4]、A[10]进行比较

A[5]、A[11]进行比较

A[0]、A[6]、A[12]进行比较

第二趟增量为3,将数组A中相邻间隔为3的元素进行比较。

因此:

A[3]、A[0]进行比较

A[4]、A[1]进行比较

A[5]、A[2]进行比较

A[6]、A[3]、A[0]进行比较

A[7]、A[4]、A[1]进行比较

A[8]、A[5]、A[2]进行比较

A[9]、A[6]、A[3]、A[0]进行比较

A[10]、A[7]、A[4]、A[1]进行比较

A[11]、A[8]、A[5]、A[2]进行比较

A[12]、A[9]、A[6]、A[3]、A[0]进行比较

第三趟增量为1,将数组A中相邻间隔为1的元素进行比较。

因此:

A[1]、A[0]进行比较

A[2]、A[1]、A[0]进行比较

A[3]、A[2]、A[1]、A[0]进行比较

A[4]、A[3]、A[2]、A[1]、A[0]进行比较

A[5]、A[4]、A[3]、A[2]、A[1]、A[0]进行比较

A[6]、A[5]、A[4]、A[3]、A[2]、A[1]、A[0]进行比较

A[7]、A[6]、A[5]、A[4]、A[3]、A[2]、A[1]、A[0]进行比较

A[8]、A[7]、A[6]、A[5]、A[4]、A[3]、A[2]、A[1]、A[0]进行比较

A[9]、A[8]、A[7]、A[6]、A[5]、A[4]、A[3]、A[2]、A[1]、A[0]进行比较

A[10]、A[9]、A[8]、A[7]、A[6]、A[5]、A[4]、A[3]、A[2]、A[1]、A[0]进行比较

A[11]、A[10]、A[9]、A[8]、A[7]、A[6]、A[5]、A[4]、A[3]、A[2]、A[1]、A[0]进行比较

A[12]、A[11]、A[10]、A[9]、A[8]、A[7]、A[6]、A[5]、A[4]、A[3]、A[2]、A[1]、A[0]进行比较

  • 程序实现

#include<iostream>
using namespace std;
void print(int a[], int n ,int i){  
    cout<<i <<":";  
    for(int j= 0; j<n; j++){  
        cout<<a[j] <<" ";  
    }  
    cout<<endl;  
}  
void ShellInsertSort(int a[], int n, int dk)  
{  
    int i,j,p;
    int Tmp;
    for(i=dk;i<n;i++)  
    {
        Tmp=a[i];
        for(j=i;j>=dk;j-=dk)  
            if(Tmp<a[j-dk])
                a[j]=a[j-dk];
            else
                break;
        a[j]=Tmp;
        print(a,n,i);  
    }
      
}  
/** 
 * 先按增量d(n/2,n为要排序数的个数进行希尔排序 
 * 
 */  
void shellSort(int a[], int n){  
  
    int dk = n/2;  
    while( dk >= 1  ){  
        ShellInsertSort(a, n, dk);  
        dk = dk/2;  
    }  
} 
  
int main(){  
    int a[13] = {81,94,11,96,12,35,17,95,28,58,41,75,15};  
    shellSort(a,13);  
    system("pause");
    return 0;
}

  • 分析

希尔排序需要三层for循环,第一层for循环确定每趟希尔排序的增量,第二层循环确定哨兵元素位置,第三层for循环比较从哨兵元素到位置0上每相邻dk元素的大小,并将哨兵元素放到合适位置上。在程序中我们采用和插入排序相同的方法避免明显的使用交换。

我们将增量选择为n/2,但并不是最好的,希尔排序的时间界与增量序列的选取有关。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值