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