为何希尔排序(Shell Sort)比插入排序(Insertion Sort)更高效?
希尔排序比插入排序高效的核心原因
你抓的点没错——希尔排序最后确实要跑一次gap=1的插入排序,但它的优势全在前面的gap预处理把数组变得极度接近有序,而插入排序在接近有序的数组上效率会飙升到近乎O(n),这才是关键。
先搞懂插入排序的真正痛点
插入排序的O(n²)复杂度,本质是因为数组无序时,每个元素可能需要移动大量步数。比如最小的元素在数组最后,插入排序要把它一步一步挪到开头,得做n-1次交换;每个元素都这么折腾,总操作次数就是n²级别。但如果数组本来就接近有序,每个元素只需要移动0~2步,那插入排序的实际耗时会接近O(n),比很多O(n log n)的算法都快。
希尔排序的gap是在“隔空挪元素”
希尔排序的不同gap,本质是在做多轮粗粒度排序:
- 大gap的时候,数组被拆成多个间隔为gap的子数组,每个子数组的元素数量少,插入排序的成本很低;
- 更重要的是,大gap允许元素跨大步移动——比如一个本该在数组前半段的大元素现在在后半段,gap=5时一次就能往前跳5个位置,不用像普通插入排序那样一步一步挪。这能快速把元素放到接近它最终位置的地方,大幅减少后续gap=1时的移动次数。
最后gap=1的插入排序是“捡漏”
经过多轮不同gap的排序后,数组已经几乎完全有序了。这时候跑插入排序,绝大多数元素根本不需要移动,少数需要调整的元素也只需要动1~2步。这阶段的耗时几乎是O(n),和直接跑原生插入排序的O(n²)完全不是一个量级。
举个直观的例子
比如乱序数组[9,8,7,6,5,4,3,2,1]:
- 直接跑插入排序:每个元素都要从后往前挪到底,总交换次数是36次;
- 希尔排序用gap=4→2→1:
- gap=4时,排序后数组变成
[1,4,3,2,5,8,7,6,9],仅用了8次交换; - gap=2时,排序后数组变成
[1,2,3,4,5,6,7,8,9],仅用了4次交换; - gap=1时,数组已经有序,0次交换。
总交换次数12次,只有插入排序的1/3。
- gap=4时,排序后数组变成
内容的提问来源于stack exchange,提问作者Gargouri Nourallah
相关产品推荐
相关产品推荐

