排序算法三:Shell插入排序


声明:引用请注明出处http://blog.csdn.net/lg1259156776/


引言

在我的博文《“主宰世界”的10种算法短评》中给出的首个算法就是高效的排序算法。本文将对排序算法做一个全面的梳理,从最简单的“冒泡”到高效的堆排序等。

上一篇博文《排序算法二:二分(折半)插入排序》讲述了直接插入排序,本文讲述第三种插入排序算法:Shell插入排序。实际上它是改进自插入排序和冒泡排序。


排序相关的的基本概念

  • 排序:将一组杂乱无章的数据按一定的规律顺次排列起来。

    • 数据表( data list): 它是待排序数据对象的有限集合。
    • 排序码(key):通常数据对象有多个属性域,即多个数据成员组成,其中有一个属性域可用来区分对象,作为排序依据。该域即为排序码。每个数据表用哪个属性域作为排序码,要视具体的应用需要而定。
  • 分类
    • 内排序:指在排序期间数据对象全部存放在内存的排序;
    • 外排序:指在排序期间全部对象个数太多,不能同时存放在内存,必须根据排序过程的要求,不断在内、外存之间移动的排序。

排序算法的分析

排序算法的稳定性

如果在对象序列中有两个对象r[i]和r[j] ,它们的排序码k[i]==k[j] 。如果排序前后,对象r[i]和r[j] 的相对位置不变,则称排序算法是稳定的;否则排序算法是不稳定的。

排序算法的评价

时间开销

  • 排序的时间开销可用算法执行中的数据比较次数与数据移动次数来衡量。
  • 算法运行时间代价的大略估算一般都按平均情况进行估算。对于那些受对象排序码序列初始排列及对象个数影响较大的,需要按最好情况和最坏情况进行估算

空间开销

算法执行时所需的附加存储。


Shell插入排序

基本思想

先取一个小于n的整数d1作为第一个增量,把文件的全部记录分成d1个组。所有距离为dl的倍数的记录放在同一个组中。先在各组内进行直接插人排序;然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量dt=1(dt<dt−l<…<d2<d1),即所有记录放在同一组中进行直接插入排序为止。该方法实质上是一种分组插入方法。实际上当dt=1时,完全就是直接插入排序。但是经过多个分组的直接插入排序,最后一次完整的插入排序前数据表几乎已经是排好序了,因此shell sort充分利用了直接插入排序在数据表几乎已经有序的条件下工作高效的特点。

算法的C plus plus实现

根据算法的基本思想,shell插入排序的实现还是比较容易的,其C++实现如下:

#include <iostream>
#include <iomanip>
using namespace std; void print(int ar[], int sz, int step)
{
for(int i = 0; i < sz; ++i) {
if(((i + 1) % step) != 0)
cout << setw(3) << ar[i];
else
cout << setw(3) << ar[i] << endl; }
cout << endl;
} void ShellSort(int a[], int sz)
{
int i, j;
int step, temp;
step = sz / 2 ;
while(step) {
print(a, sz, step);
cout << "==>" << endl;
for (i = step; i < sz; i++) {
temp = a[i];
j = i;
while (j >= step && a[j - step] > temp) {
a[j] = a[j - step];
j = j - step;
}
a[j] = temp;
}
print(a, sz, step);
cout << "current array" << endl;
print(a, sz, sz);
cout << "----------------" << endl; step = step / 2.2;
}
} int main(void)
{
int a[] = {13, 14, 94, 33, 82, 25, 59, 94, 65, 23, 45, 27, 73, 25, 39, 10};
const size_t sz = sizeof(a)/sizeof(a[0]); cout << "Initial array" << endl;
print(a,sz,sz);
cout << "-------------" << endl; ShellSort(a,sz); cout << "Sorted array" << endl;
print(a,sz,sz);
return 0;
}

核心部分ShellSort中内层的while循环实现的是查找相应组内的插入位置,并提前进行位置的交换。而for循环控制的是从每个组内的第2个数开始重复在该组前面有序的数据表中实现直接插入排序。与直接插入排序的区别是shell插入排序一次for将所有组内的第i个数插入到各自前i-1个有序表中。

输出为:

Initial array
13 14 94 33 82 25 59 94 65 23 45 27 73 25 39 10 -------------
13 14 94 33 82 25 59 94
65 23 45 27 73 25 39 10 ==>
13 14 45 27 73 25 39 10
65 23 94 33 82 25 59 94 current array
13 14 45 27 73 25 39 10 65 23 94 33 82 25 59 94 ----------------
13 14 45
27 73 25
39 10 65
23 94 33
82 25 59
94
==>
13 10 25
23 14 33
27 25 45
39 73 59
82 94 65
94
current array
13 10 25 23 14 33 27 25 45 39 73 59 82 94 65 94 ----------------
13
10
25
23
14
33
27
25
45
39
73
59
82
94
65
94 ==>
10
13
14
23
25
25
27
33
39
45
59
65
73
82
94
94 current array
10 13 14 23 25 25 27 33 39 45 59 65 73 82 94 94 ----------------
Sorted array
10 13 14 23 25 25 27 33 39 45 59 65 73 82 94 94

算法分析

  1. 增量序列的选择

    Shell排序的执行时间依赖于增量序列。

    好的增量序列的共同特征:

    • 最后一个增量必须为1;
    • 应该尽量避免序列中的值(尤其是相邻的值)互为倍数的情况。

      有人通过大量的实验,给出了目前较好的结果:当n较大时,比较和移动的次数约在nl.25到1.6nl.25之间。
  2. Shell排序的时间性能优于直接插入排序

    希尔排序的时间性能优于直接插入排序的原因:

    • 当数据表初态基本有序时直接插入排序所需的比较和移动次数均较少。
    • 当n值较小时,n和n2的差别也较小,即直接插入排序的最好时间复杂度O(n)和最坏时间复杂度0(n2)差别不大。
    • 在希尔排序开始时增量较大,分组较多,每组的记录数目少,故各组内直接插入较快,后来增量di逐渐缩小,分组数逐渐减少,而各组的记录数目逐渐增多,但由于已经按di−1作为距离排过序,使数据表较接近于有序状态,所以新的一趟排序过程也较快。

      因此,希尔排序在效率上较直接插人排序有较大的改进。
  3. 稳定性

    希尔排序是不稳定的。两个相同关键字在排序前后的相对次序是可能发生变化的。

这个方法对于大的数据集效率其实并不高,但是它是一个对小数量数据表(小于1000)进行排序的最快算法之一。另外,相对使用的内存较少。


2015-9-24 艺少

排序算法三:Shell插入排序的更多相关文章

  1. python实现排序算法三:插入排序

    插入排序基本思想:假设一个无序数组A,则对于只有一个元素A[0]的子数组C来讲,其是有序的,然后将A[1]插入到C中,则就是将A[1]与A[0]进行比较,如果A[1]比A[0]小,则交换两者的顺序,这 ...

  2. Java常见排序算法之Shell排序

    在学习算法的过程中,我们难免会接触很多和排序相关的算法.总而言之,对于任何编程人员来说,基本的排序算法是必须要掌握的. 从今天开始,我们将要进行基本的排序算法的讲解.Are you ready?Let ...

  3. Java常见排序算法之直接插入排序

    在学习算法的过程中,我们难免会接触很多和排序相关的算法.总而言之,对于任何编程人员来说,基本的排序算法是必须要掌握的. 从今天开始,我们将要进行基本的排序算法的讲解.Are you ready?Let ...

  4. Java常见排序算法之折半插入排序

    在学习算法的过程中,我们难免会接触很多和排序相关的算法.总而言之,对于任何编程人员来说,基本的排序算法是必须要掌握的. 从今天开始,我们将要进行基本的排序算法的讲解.Are you ready?Let ...

  5. 排序算法之直接插入排序Java实现

    排序算法之直接插入排序 舞蹈演示排序: 冒泡排序: http://t.cn/hrf58M 希尔排序:http://t.cn/hrosvb  选择排序:http://t.cn/hros6e  插入排序: ...

  6. 七内部排序算法汇总(插入排序、Shell排序、冒泡排序、请选择类别、、高速分拣合并排序、堆排序)

    写在前面: 排序是计算机程序设计中的一种重要操作,它的功能是将一个数据元素的随意序列,又一次排列成一个按keyword有序的序列.因此排序掌握各种排序算法很重要. 对以下介绍的各个排序,我们假定全部排 ...

  7. 我的Java开发学习之旅------>Java经典排序算法之二分插入排序

    一.折半插入排序(二分插入排序) 将直接插入排序中寻找A[i]的插入位置的方法改为采用折半比较,即可得到折半插入排序算法.在处理A[i]时,A[0]--A[i-1]已经按关键码值排好序.所谓折半比较, ...

  8. IOS算法(三)之插入排序

    直接插入排序(Insertion Sort)的基本思想是:每次将一个待排序的记录,按其keyword大小插入到前面已经排好序的子序列中的适当位置,直到所有记录插入完毕为止. 设数组为a[0-n-1]. ...

  9. 结构-行为-样式-Js排序算法之 直接插入排序

    最新因工作原因需要接触到算法,之前学习C++的时候有接触过算法,Javascript中实现算法其实也是大同小异.下面我讲下第一个实现的排序算法--直接插入排序.基本实现思路:假定一个数组中前n(n&g ...

随机推荐

  1. sublime 不是插件安装越多越好,如xxxsnippet 自动完成插件太多,就非常耗电脑性能,经常性的卡着不动

    sublime 不是插件安装越多越好,如xxxsnippet 自动完成插件太多,就非常耗电脑性能,经常性的卡着不动

  2. Linux 硬件软件时间同步

    同步BIOS时钟,强制把系统时间写入CMOS clock --show   查看硬件时间clock -w       强制把系统时间写入CMOSclock --show   查看硬件时间reboot ...

  3. tinymce编辑器从word粘贴公式

    很多时候我们用一些管理系统的时候,发布新闻.公告等文字类信息时,希望能很快的将word里面的内容直接粘贴到富文本编辑器里面,然后发布出来.减少排版复杂的工作量. 下面是借用百度doc 来快速实现这个w ...

  4. Ubuntu输入ifconfig找不到IP地址,只有lo问题

    首先我的问题是这样的 然后一顿神百度,要找到你之前用的网卡或者设备,ifconfig -a,然后好用,出来了 但是并没有IP地址什么的,网上给的重启命令也没有用 输入的命令是:ifconfig ens ...

  5. mysql PS1个性化

    method ) $ export MYSQL_PS1="\u@\h [\d]> " method ) mysql> prompt \u@\h [\d]> met ...

  6. 【转】Python基础-字符串

    原文地址http://blog.chinaunix.net/uid-21169302-id-446256.html Python-String-Function 字符串中字符大小写的变换: * S.l ...

  7. Buuctf pwn1 详细wp

    目录 程序基本信息 程序溢出点 确定返回地址 编写exp脚本 成功getshell 程序基本信息 我们可以看到这是一个64程序,没有保护开启. 程序溢出点 gets函数可以读取无限字符,存在栈溢出. ...

  8. Flutter移动电商实战 --(43)详细页_补充首页跳转到详细页

    首页轮播点击到详细页 修改我们轮播这里的代码:SwiperDiy这个类这里的代码 return InkWell( onTap: (){ Application.router.navigateTo(co ...

  9. 在从myql服务器上 取消主从关系和重新构建主从关系

    取消主从关系 mysql -uroot -p mysql>show slave status\G; 查看主库是否为之前的ip mysql>change master to master_h ...

  10. 知乎千万级高性能长连接网关 https://zhuanlan.zhihu.com/p/66807833

    知乎千万级高性能长连接网关揭秘 9 天前 · 来自专栏 知乎技术专栏 实时的响应总是让人兴奋的,就如你在微信里看到对方正在输入,如你在王者峡谷里一呼百应,如你们在直播弹幕里不约而同的 666,它们的背 ...