算法系列之五 希尔排序
對于前面講過的基礎排序來說,他們在實際使用的時候,價值并不是太大。它的價值在于,體現了一種很好的思想。通過一些改進和變化,可以達到一個不錯的性能。希爾排序就是典型的一個例子,它改進了插入排序,使得算法的實用性大大增加,對于中等數組,當需要用排序解決問題,又不能使用系統排序的時候,這是一個不錯的選擇。
希爾排序的思想
首先,我們來回憶一下,插入排序的優點,它有兩個優點:
希爾排序就是充分利用了這兩個優點,來優化插入排序。那么,希爾排序做了哪些改動呢:
1. 將數組分隔成更小的數組
希爾排序假設一個值 h, 將數列中,間隔為 h 的元素,作為一個新的子數列,這時,將整個大的數列分成了若干小數列,然后挨個處理子數列。因為 優點1,所以希爾排序會表現得很快。然后減小 h 的值,直到 1。
2. 對基本有序的大數列排序
當 h=1 的時候,就是對整個數組運行一遍插入排序,數組有序。因為之前的操作,使得整個數列已經處于基本有序的狀態了。這時充分利用了 優點2,排序也會表現得很快。
代碼如下:
void shell_sort(int *a, int length) {int h;// 選擇一個 小于數組長度,可能最大的間隔值// 1, 4, 13, 40, 121, 364 ....for (h = 1; h < length / 3; h = 3 * h + 1);while (h >= 1) {// 對間隔 h 的每個元素進行處理for (int i = h; i < length; i++) {for (int j = i; j >= h && a[j-h] > a[j]; j -= h) {swap(a, j, j - h);}}h = h / 3;} }上面的代碼中,在第一個for循環的地方,產生了一個遞增的數列。后面的 while 循環,按照這個數列來遞減,處理整個待排序數組。
希爾排序的性能,很大程度上取決于這個 遞增數列。所以,如何產生這個數列是一個值得研究的話題。有很多論文研究了各種不同的遞增數列,但是都沒有辦法證明是最好的。
對于一些復雜實現的 遞增數列,在最壞的情況下,性能要好于我們這個版本的。但是,在平均的情況下,使用 3*h+1 這個簡單的方法,和復雜實現的性能是接近的。
結尾
希爾排序的性能計算一直是一個很難的問題。目前只能說,它是小于插入排序的 \(O(N^2)\) 的復雜度。在我們的版本中,已知最壞的情況下,比較次數和 \(N^{3/2}\)成正比。
但是,通過一點小的改變就能,就能突破平方級,是很多算法設計要達到的目標。
作者和出處(reposkeeper) 授權分享 By CC BY-SA 4.0
轉載于:https://www.cnblogs.com/reposkeeper-wx/p/suan-fa-xi-lie-zhi-wu-xi-er-pai-xu.html
總結
以上是生活随笔為你收集整理的算法系列之五 希尔排序的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【NOIP2002】【codevs109
- 下一篇: JUnit 测试含有控制台输入的方法