希尔排序介绍

希尔排序(Shell Sort)是插入排序的一种,它是针对直接插入排序算法的改进。该方法又称缩小增量排序,因DL.Shell于1959年提出而得名。

希尔排序实质上是一种分组插入方法。它的基本思想是:对于n个待排序的数列,取一个小于n的整数gap(gap被称为步长)将待排序元素分成若干个组子序列,所有距离为gap的倍数的记录放在同一个组中;然后,对各组内的元素进行直接插入排序。 这一趟排序完成之后,每一个组的元素都是有序的。然后减小gap的值,并重复执行上述的分组和排序。重复这样的操作,当gap=1时,整个数列就是有序的。

下面以数列{80,30,60,40,20,10,50,70}为例,演示它的希尔排序过程。

第1趟:(gap=4)

当gap=4时,意味着将数列分为4个组: {80,20},{30,10},{60,50},{40,70}。 对应数列: {80,30,60,40,20,10,50,70}
对这4个组分别进行排序,排序结果: {20,80},{10,30},{50,60},{40,70}。 对应数列: {20,10,50,40,80,30,60,70}

第2趟:(gap=2)

当gap=2时,意味着将数列分为2个组:{20,50,80,60}, {10,40,30,70}。 对应数列: {20,10,50,40,80,30,60,70}
注意:{20,50,80,60}实际上有两个有序的数列{20,80}和{50,60}组成。
          {10,40,30,70}实际上有两个有序的数列{10,30}和{40,70}组成
对这2个组分别进行排序,排序结果:{20,50,60,80}, {10,30,40,70}。 对应数列: {20,10,50,30,60,40,80,70}

第3趟:(gap=1)

当gap=1时,意味着将数列分为1个组:{20,10,50,30,60,40,80,70}
注意:{20,10,50,30,60,40,80,70}实际上有两个有序的数列{20,50,60,80}和{10,30,40,70}组成。
对这1个组分别进行排序,排序结果:{10,20,30,40,50,60,70,80}

希尔排序的时间复杂度和稳定性

希尔排序时间复杂度
希尔排序的时间复杂度与增量(即,步长gap)的选取有关。例如,当增量为1时,希尔排序退化成了直接插入排序,此时的时间复杂度为O(N²),而Hibbard增量的希尔排序的时间复杂度为O(N3/2)。

希尔排序稳定性
希尔排序是不稳定的算法,它满足稳定算法的定义。对于相同的两个数,可能由于分在不同的组中而导致它们的顺序发生变化。
算法稳定性 -- 假设在数列中存在a[i]=a[j],若在排序之前,a[i]在a[j]前面;并且排序之后,a[i]仍然在a[j]前面。则这个排序算法是稳定的!

希尔排序实现

希尔排序C实现
实现代码(shell_sort.c)

 /**
2 * 希尔排序:C 语言
3 *
4 * @author skywang
5 * @date 2014/03/11
6 */ #include <stdio.h> // 数组长度
#define LENGTH(array) ( (sizeof(array)) / (sizeof(array[0])) ) /*
14 * 希尔排序
15 *
16 * 参数说明:
17 * a -- 待排序的数组
18 * n -- 数组的长度
19 */
void shell_sort1(int a[], int n)
{
int i,j,gap; // gap为步长,每次减为原来的一半。
for (gap = n / ; gap > ; gap /= )
{
// 共gap个组,对每一组都执行直接插入排序
for (i = ;i < gap; i++)
{
for (j = i + gap; j < n; j += gap)
{
// 如果a[j] < a[j-gap],则寻找a[j]位置,并将后面数据的位置都后移。
if (a[j] < a[j - gap])
{
int tmp = a[j];
int k = j - gap;
while (k >= && a[k] > tmp)
{
a[k + gap] = a[k];
k -= gap;
}
a[k + gap] = tmp;
}
}
} }
} /*
51 * 对希尔排序中的单个组进行排序
52 *
53 * 参数说明:
54 * a -- 待排序的数组
55 * n -- 数组总的长度
56 * i -- 组的起始位置
57 * gap -- 组的步长
58 *
59 * 组是"从i开始,将相隔gap长度的数都取出"所组成的!
60 */
void group_sort(int a[], int n, int i,int gap)
{
int j; for (j = i + gap; j < n; j += gap)
{
// 如果a[j] < a[j-gap],则寻找a[j]位置,并将后面数据的位置都后移。
if (a[j] < a[j - gap])
{
int tmp = a[j];
int k = j - gap;
while (k >= && a[k] > tmp)
{
a[k + gap] = a[k];
k -= gap;
}
a[k + gap] = tmp;
}
}
} /*
83 * 希尔排序
84 *
85 * 参数说明:
86 * a -- 待排序的数组
87 * n -- 数组的长度
88 */
void shell_sort2(int a[], int n)
{
int i,gap; // gap为步长,每次减为原来的一半。
for (gap = n / ; gap > ; gap /= )
{
// 共gap个组,对每一组都执行直接插入排序
for (i = ;i < gap; i++)
group_sort(a, n, i, gap);
}
} void main()
{
int i;
int a[] = {,,,,,,,};
int ilen = LENGTH(a); printf("before sort:");
for (i=; i<ilen; i++)
printf("%d ", a[i]);
printf("\n"); shell_sort1(a, ilen);
//shell_sort2(a, ilen); printf("after sort:");
for (i=; i<ilen; i++)
printf("%d ", a[i]);
printf("\n");
}

希尔排序Java实现
实现代码(ShellSort.java)

 /**
2 * 希尔排序:Java
3 *
4 * @author skywang
5 * @date 2014/03/11
6 */
7
8 public class ShellSort {
9
10 /**
11 * 希尔排序
12 *
13 * 参数说明:
14 * a -- 待排序的数组
15 * n -- 数组的长度
16 */
17 public static void shellSort1(int[] a, int n) {
18
19 // gap为步长,每次减为原来的一半。
20 for (int gap = n / 2; gap > 0; gap /= 2) {
21
22 // 共gap个组,对每一组都执行直接插入排序
23 for (int i = 0 ;i < gap; i++) {
24
25 for (int j = i + gap; j < n; j += gap) {
26
27 // 如果a[j] < a[j-gap],则寻找a[j]位置,并将后面数据的位置都后移。
28 if (a[j] < a[j - gap]) {
29
30 int tmp = a[j];
31 int k = j - gap;
32 while (k >= 0 && a[k] > tmp) {
33 a[k + gap] = a[k];
34 k -= gap;
35 }
36 a[k + gap] = tmp;
37 }
38 }
39 }
40 }
41 }
42
43 /**
44 * 对希尔排序中的单个组进行排序
45 *
46 * 参数说明:
47 * a -- 待排序的数组
48 * n -- 数组总的长度
49 * i -- 组的起始位置
50 * gap -- 组的步长
51 *
52 * 组是"从i开始,将相隔gap长度的数都取出"所组成的!
53 */
54 public static void groupSort(int[] a, int n, int i,int gap) {
55
56 for (int j = i + gap; j < n; j += gap) {
57
58 // 如果a[j] < a[j-gap],则寻找a[j]位置,并将后面数据的位置都后移。
59 if (a[j] < a[j - gap]) {
60
61 int tmp = a[j];
62 int k = j - gap;
63 while (k >= 0 && a[k] > tmp) {
64 a[k + gap] = a[k];
65 k -= gap;
66 }
67 a[k + gap] = tmp;
68 }
69 }
70 }
71
72 /**
73 * 希尔排序
74 *
75 * 参数说明:
76 * a -- 待排序的数组
77 * n -- 数组的长度
78 */
79 public static void shellSort2(int[] a, int n) {
80 // gap为步长,每次减为原来的一半。
81 for (int gap = n / 2; gap > 0; gap /= 2) {
82 // 共gap个组,对每一组都执行直接插入排序
83 for (int i = 0 ;i < gap; i++)
84 groupSort(a, n, i, gap);
85 }
86 }
87
88 public static void main(String[] args) {
89 int i;
90 int a[] = {80,30,60,40,20,10,50,70};
91
92 System.out.printf("before sort:");
93 for (i=0; i<a.length; i++)
94 System.out.printf("%d ", a[i]);
95 System.out.printf("\n");
96
97 shellSort1(a, a.length);
98 //shellSort2(a, a.length);
99
100 System.out.printf("after sort:");
101 for (i=0; i<a.length; i++)
102 System.out.printf("%d ", a[i]);
103 System.out.printf("\n");
104 }
105 }

C数据结构排序算法——希尔排序法用法总结(转http://www.cnblogs.com/skywang12345/p/3597597.html)的更多相关文章

  1. 数据结构和算法(Golang实现)(22)排序算法-希尔排序

    希尔排序 1959 年一个叫Donald L. Shell (March 1, 1924 – November 2, 2015)的美国人在Communications of the ACM 国际计算机 ...

  2. 排序算法--希尔排序(Shell Sort)_C#程序实现

    排序算法--希尔排序(Shell Sort)_C#程序实现 排序(Sort)是计算机程序设计中的一种重要操作,也是日常生活中经常遇到的问题.例如,字典中的单词是以字母的顺序排列,否则,使用起来非常困难 ...

  3. 使用 js 实现十大排序算法: 希尔排序

    使用 js 实现十大排序算法: 希尔排序 希尔排序 refs xgqfrms 2012-2020 www.cnblogs.com 发布文章使用:只允许注册用户才可以访问!

  4. C数据结构排序算法——直接插入排序法用法总结(转http://blog.csdn.net/lg1259156776/)

    声明:引用请注明出处http://blog.csdn.net/lg1259156776/ 排序相关的的基本概念 排序:将一组杂乱无章的数据按一定的规律顺次排列起来. 数据表( data list): ...

  5. Python排序算法——希尔排序(Shell’s Sort)

    有趣的事,Python永远不会缺席! 如需转发,请注明出处:小婷儿的python https://www.cnblogs.com/xxtalhr/p/10793487.html 一.希尔排序(Shel ...

  6. js 实现排序算法 -- 希尔排序(Shell Sort)

    原文: 十大经典排序算法(动图演示) 希尔排序 1959年Shell发明,第一个突破O(n2)的排序算法,是简单插入排序的改进版.它与插入排序的不同之处在于,它会优先比较距离较远的元素.希尔排序又叫缩 ...

  7. JavaScript排序算法——希尔排序

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  8. 排序算法-希尔排序(Java)

    package com.rao.sort; import java.util.Arrays; /** * @author Srao * @className ShellSort * @date 201 ...

  9. java数据结构和算法------希尔排序

    package iYou.neugle.sort; public class Shell_sort { public static void ShellSort(double[] array) { i ...

随机推荐

  1. HDU3844Mining Your Own Business

    目测某年HNOI,(其实这个题是2011年的WF,hdu上找到的,HNOI2012那个中文题在bzoj和loj上都有,叫矿场搭建,题意几乎一样,数据比较弱,交这份代码也能A). 先讲题解,然后说一些有 ...

  2. C++入门经典-例9.4-默认模板参数

    1:默认模板参数就是在类模板定义时设置类型形式参数表中的一个类型参数的默认值,该默认值是一个数据类型.有了默认的数据类型参数后,在定义模板的新类型时就可以不进行指定.代码如下: // 9.4.cpp ...

  3. dubbo的实现原理

    dubbo的介绍 dubbo是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的RPC实现服务的输出和输入功能,可以和Spring框架无缝集成. dubbo框架是基于Spring容器运 ...

  4. (八)C语言之printf

  5. UFLDL(Unsupervised Feature Learning and Deep Learning)

    UFLDL(Unsupervised Feature Learning and Deep Learning)Tutorial 是由 Stanford 大学的 Andrew Ng 教授及其团队编写的一套 ...

  6. LeetCode 145. 二叉树的后序遍历(Binary Tree Postorder Traversal)

    题目描述 给定一个二叉树,返回它的 后序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [3,2,1] 进阶: 递归算法很简单,你可以通过迭代算法完成吗? 解题思路 后 ...

  7. java实现几种常用排序:冒泡排序

    一.冒泡排序介绍 冒泡排序是我们得最多的排序方式之一,原因是简单易实现,且原理易懂.顾名思义,冒泡排序,它的排序过程就像水中的气泡一样,一个一个上浮到水面. 二.冒泡排序原理分析 三.冒泡排序代码实现 ...

  8. linux常用关机和重启命令

    Linux有如下的关机和重启命令:shutdown, reboot, halt, poweroff,那么它们有什么区别呢? shutdown - 建议使用的命令 shutdown是最常用也是最安全的关 ...

  9. LC 655. Print Binary Tree

    Print a binary tree in an m*n 2D string array following these rules: The row number m should be equa ...

  10. Workflow-产品:泛微工作流引擎

    ylbtech-Workflow-产品:泛微工作流引擎 1.返回顶部 1. 工作流引擎平台技术架构 TECHNOLOGY FRAMEWORK 高度协同系统各应用模块 泛微工作流引擎平台是整个协同办公平 ...