常用的排序算法之希尔排序(Shell Sort)
希尔排序(Shell Sort)
起源
希尔排序(Shell Sort)是Donald Shell于1959年提出的一种基于插入排序的算法。它是对直接插入排序算法的一种更高效的改进版本,也称为“缩小增量排序”。
定义
希尔排序是插入排序的一种更高效的改进版本,也称为缩小增量排序。希尔排序是非稳定排序算法。该方法的基本思想是:先将整个待排序的记录序列分割成为若干子序列(由相隔某个“增量”的记录组成)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的记录“基本有序”时,再对全体记录进行一次直接插入排序。
引伸义
希尔排序的引伸义在于其“增量”的选取。增量序列的选取对希尔排序的效率有很大的影响。不同的增量序列可能带来不同的时间复杂度。例如,Hibbard提出了另一个增量序列{1, 3, 7, ..., 2^k-1},称为Hibbard增量,在最好情况下时间复杂度为O(n^(3/2))。还有更复杂的增量序列,如Sedgewick增量,旨在进一步减少希尔排序的比较次数。
优缺点
优点:
- 希尔排序是基于插入排序的,因此它保持了插入排序的稳定性(当增量为1时)和简单性。
- 相比插入排序,希尔排序在数据量大且无序的情况下效率更高。
缺点:
- 希尔排序的时间复杂度与增量序列的选取有关,最坏情况下时间复杂度仍为O(n^2)。
- 希尔排序不是稳定的排序算法,因为不同的增量可能导致相等元素的相对顺序发生变化。
使用场景
希尔排序适用于中等规模的数据排序,对于大规模数据,更高效的排序算法(如快速排序、归并排序等)可能更为合适。此外,希尔排序由于其简单性和稳定性(当增量为1时),也常用于教学示例。
使用数据一步步举例
假设有一个数组[9, 8, 3, 7, 5, 6, 4, 1]
,我们使用希尔排序(增量序列为[4, 2, 1])来对其进行升序排序:
- 增量为4:将数组分成四个子序列[9, 5],[8, 4],[3, 1],[7, 6],分别进行插入排序。
- [5, 9],[4, 8],[1, 3],[6, 7]
- 增量为2:将数组分成两个子序列[5, 4, 1, 6]和[9, 8, 3, 7],分别进行插入排序。
- [4, 1, 5, 6],[7, 3, 8, 9]
- 增量为1:此时整个数组已经基本有序,进行一次插入排序即可。
- [1, 3, 4, 5, 6, 7, 8, 9]
Java示例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | public class ShellSort { public static void main(String[] args) { int [] array = { 9 , 8 , 3 , 7 , 5 , 6 , 4 , 1 }; shellSort(array); System.out.println(Arrays.toString(array)); } public static void shellSort( int [] array) { int n = array.length; int gap = n / 2 ; // 初始增量 // 动态定义间隔序列 while (gap > 0 ) { for ( int i = gap; i < n; i++) { int temp = array[i]; int j; for (j = i; j >= gap && array[j - gap] > temp; j -= gap) { array[j] = array[j - gap]; } array[j] = temp; } gap /= 2 ; // 减小增量 } } } |
运行上述代码,将输出排序后的数组[1, 3, 4, 5, 6, 7, 8, 9]
。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App