希尔排序的概述:
a[0]...a[n-1] 将n个元素的数组,进行分组。同组内元素的索引相差gap(我们称之为步长)。
第一次步长计算方式为 gap = n/2,第二次步长计算方式为 gap = gap/2...依次类推,直到gap = 0。每一次,对每个分组内的元素进行直接插入排序。最后对整一个数组进行直接插入排序,由于整个数组已经基本有序了,因此最后执行直接插入排序效率非常高。
对于以下这个数组我们来模拟希尔排序的整个过程,以更形象地理解希尔排序的原理
49 38 65 97 26 13 27 49 55 4
第一次:gap = 10 / 2 = 5
49 | 38 | 65 | 97 | 26 | 13 | 27 | 49 | 55 | 4 |
A1 | A2 | ||||||||
B1 | B2 | ||||||||
C1 | C2 | ||||||||
D1 | D2 | ||||||||
E1 | E2 |
分组A执行直接插入排序后:13 49
分组B执行直接插入排序后:27 38
分组C执行直接插入排序后:49 65
分组D执行直接插入排序后:55 97
分组E执行直接插入排序后:4 26
13 | 27 | 49 | 55 | 4 | 49 | 38 | 65 | 97 | 26 |
A1 | A2 | ||||||||
B1 | B2 | ||||||||
C1 | C2 | ||||||||
D1 | D2 | ||||||||
E1 | E2 |
执行完第一次的每个分组排序后:得到数组 13,27,49,55,4,49,38,65,97,26
第二次:gap = 5 / 2 = 2
13 | 27 | 49 | 55 | 4 | 49 | 38 | 65 | 97 | 26 |
A1 | A2 | A3 | A4 | A5 | |||||
B1 | B2 | B3 | B4 | B5 |
分组A执行直接插入排序后:4 13 38 49 97
分组B执行直接插入排序后:26 27 49 55 65
4 | 26 | 13 | 27 | 38 | 49 | 49 | 55 | 97 | 65 |
A1 | A2 | A3 | A4 | A5 | |||||
B1 | B2 | B3 | B4 | B5 |
执行完第二次的每个分组排序后,得到数组4 26 13 27 38 49 49 55 97 65
第三次:gap = 2 / 2 = 1
4 | 26 | 13 | 27 | 38 | 49 | 49 | 55 | 97 | 65 |
第三次,就只有一个分组了,我们可以看到整个数组已基本有序了。对整个数组进行直接插入排序,就得到了一个拍好序的数组了。
4 | 13 | 26 | 27 | 38 | 49 | 49 | 55 | 65 | 97 |
第四次:gap = 1 / 2 = 0
结束
根据上述模拟的希尔排序过程给出希尔排序代码:
从上述分析我们可知gap为多少,就表示每次有多少个分组。
int n = array.length; for (int gap = n / 2; gap > 0; gap /= 2) { // 步长是多少,就有多少个分组 for (int m = 0; m < gap; m++) { // 对每个分组进行直接插入排序 for (int i = m + gap; i < length; i += gap) { int temp = array[i], j; // 一边判断temp(为array[i]的值)是否小于array[j],若小于array[j],则 //将array[j]后移一位 for (j = i - gap; j >= 0 && temp < array[j]; j -= gap) { array[j + gap] = array[j]; } array[j + gap] = temp; } } }
对于严格定义的希尔排序稍作改进
上述给出的代码看似有些繁琐,我们可以稍作改进,观察发现,每次对于分组的排序,都是要将该分组全部排序完后,再进行下一个分组的排序的。我们也可以这样做,以上述例子中,第二次为例,
13,27,49,55,4,49,38,65,97,26
13 | 27 | 49 | 55 | 4 | 49 | 38 | 65 | 97 | 26 |
A1 | A2 | A3 | A4 | A5 | |||||
B1 | B2 | B3 | B4 | B5 | |||||
0 | gap-1 | gap | gap+1 | gap+2 | gap+3 | gap+4 | gap+5 | gap+6 | gap+7 |
首先我们从gap开始,即从A2开始,此时对A1,A2做直接插入排序,接下来,gap+1即取B2,那么对B1,B2做直接插入排序,接下来gap+2即取A3,对A1,A2,A3做直接插入排序,接下来取gap+3即B3,做直接插入排序。。。依次类推,直到gap+9即B5对B1,B2,B3,B4,B5做直接插入排序。
不好理解的话,换种说法,还是以第二次排序为例,原来是每次从A1到A5,从B1到B5,可以改成从A2开始,先和A1比较,然后取B2与B1比较,再取A3与前面自己组内的数据比较…….。这种每次从数组第gap个元素开始,每个元素与自己组内的数据进行直接插入排序显然也是正确的。
int n = array.length; // 共需进行分组排序次数 for (int gap = n / 2; gap > 0; gap /= 2) { // 从gap个元素开始,与组内前面的元素进行直接插入排序 for (int i = gap; i < n; i++) { int j = i - gap, temp = array[i], m; for (; j >= 0 && temp < array[j]; j -= gap); if (j + gap < i) {// 如果j + gap >= i表示无需移位 for (m = i - gap; m >= j + gap; m -= gap) { array[m + gap] = array[m]; } array[j + gap] = temp;// j+gap是需要插入的位置 } } }
再将直接插入排序部分,改用边判断,边移位,下面的代码就简洁多了
int n = array.length; // 共需进行分组排序次数 for (int gap = n / 2; gap > 0; gap /= 2) { // 每次从第gap个元素开始 for (int i = gap; i < n; i++) { int j, temp = array[i]; for (j = i - gap; j >= 0 && temp < array[j]; j -= gap) { array[j + gap] = array[j]; } array[j + gap] = temp; } }
对于直接插入排序,可以参考我上一篇的文章http://jaychang.iteye.com/blog/2261560
相关推荐
排序算法是计算机科学中用于将一系列数据按照特定顺序排列的基础工具,它在数据处理和程序设计中扮演着极其重要的角色。在众多排序算法中,希尔排序、冒泡排序、插入排序和选择排序因其简洁性和易于理解性,成为了...
希尔排序(Shell Sort)是一种基于插入排序的快速排序方法,由Donald Shell于1959年提出。它的主要思想是将待排序的数据按照一定的间隔进行分组,然后对每组...对于学习和理解排序算法,希尔排序是不可或缺的一部分。
希尔排序:分别使用Java和Python实现希尔排序算法 希尔排序:分别使用Java和Python实现希尔排序算法 希尔排序:分别使用Java和Python实现希尔排序算法 希尔排序:分别使用Java和Python实现希尔排序算法 希尔排序:...
本资源提供了七大经典排序算法的实现程序,包括快速排序、冒泡排序、选择排序、归并排序、插入排序、希尔排序和堆排序。下面将逐一详细介绍这些排序算法及其原理。 1. 快速排序:由C.A.R. Hoare提出,是一种采用...
数据结构排序算法中的希尔(shell)排序,可供初学者参考
本话题主要探讨六种内部排序算法:直接插入排序、希尔排序、冒泡排序、快速排序、选择排序以及堆排序。这六种排序算法各有优劣,适用于不同的场景,接下来我们将逐一进行详细阐述。 1. **直接插入排序**: 直接...
本文将详细介绍C++中实现的希尔排序、快速排序、堆排序和归并排序这四种经典排序算法。 希尔排序,由Donald Shell于1959年提出,是一种改进的插入排序。它的基本思想是通过设置一个增量序列,将待排序的元素按照...
实现以下常用的内部排序算法并进行性能比较:"直接插入排序"," 折半插入排序"," 2—路插入排序"," 表插入排序"," 希尔排序"," 起泡排序"," 快速排序"," 简单选择排序"," 树形选择排序"," 堆排序"," 归并排序"," 链式...
python python_十大排序算法之希尔排序
本主题将详细探讨两种常用的排序算法——快速排序和希尔排序,并以C语言作为实现语言进行阐述。 **快速排序**是由英国计算机科学家C.A.R. Hoare在1960年提出的。它的基本思想是通过“分治”策略来实现高效排序。...
希尔排序(Shell Sort)是一种改进的插入排序算法,它的基本思想是将待排序的数组按照一定的间隔进行分组,对每组使用插入排序算法进行排序,然后缩小间隔,再对分组进行排序,直到间隔为1 为止。逐渐减小间隔大小的...
希尔排序(Shell Sort)是一种基于插入排序的快速排序算法,由Donald Shell于1959年提出。它的主要思想是将待排序的数据按照一个增量序列分成若干个子序列,然后对每个子序列进行插入排序,最后再进行一次全局的插入...
希尔排序(Shell Sort)是一种基于插入排序的快速排序算法,由Donald Shell于1959年提出。它的主要思想是将待排序的元素按照一定的间隔分组,对每组进行插入排序,然后逐渐减小间隔,直到间隔为1,此时整个序列视为...
本篇文章将深入探讨标题和描述中提到的九大排序算法:快速排序、冒泡排序、堆排序、希尔排序、直接插入排序、直接选择排序、基数排序、箱排序和桶排序。 1. **快速排序**:快速排序是一种基于分治策略的排序算法,...
在计算机科学中,排序算法是数据处理的重要组成部分,它们用于将一组无序的数据按照特定顺序进行排列。这里我们将深入探讨七种常用的排序算法,并通过C++语言实现它们。这七种算法分别是:冒泡排序、选择排序、直接...
排序算法汇总(选择排序、直接插入排序、冒泡排序、希尔排序、快速排序、堆排序) 本资源介绍了六种常用的排序算法:选择排序、直接插入排序、冒泡排序、希尔排序、快速排序和堆排序。下面对每种算法进行详细介绍:...
该源文件包括三种排序算法,实现效率教高,代码量也不大
(1) 完成5种常用内部排序算法的演示,5种排序算法为:快速排序,直接插入排序,选择排序,堆排序,希尔排序; (2) 待排序元素为整数,排序序列存储在数据文件中,要求排序元素不少于30个; (3) 演示程序开始,...
排序算法汇总P: 冒泡排序快速排序直接选择排序插入排序希尔排序 堆排序........
希尔排序(Shell Sort)是一种基于插入排序的快速排序算法,由Donald Shell于1959年提出。它的主要思想是将待排序的数据按照一个增量序列分成若干个子序列,然后分别对每个子序列进行插入排序,最后再进行一次全局的...