《算法》筆記 3 - 選擇排序、插入排序履怯、希爾排序

  • 排序通用代碼
  • 選擇排序
  • 插入排序
  • 希爾排序

排序通用代碼

通用代碼支持任意實(shí)現(xiàn)了Comparable接口的數(shù)據(jù)類型的排序回还,不同的排序算法的差異體現(xiàn)在sort方法的實(shí)現(xiàn)上。

public class Selection {
    public static void sort(Comparable[] a) {
        //待實(shí)現(xiàn)
    }

    private static boolean less(Comparable a, Comparable b) {
        return a.compareTo(b) < 0;
    }

    private static void exch(Comparable[] a, int i, int j) {
        Comparable swap = a[i];
        a[i] = a[j];
        a[j] = swap;
    }

    private static boolean isSorted(Comparable[] a) {
        for (int i = 1; i < a.length; i++) {
            if (less(a[i], a[i - 1])) {
                return false;
            }
        }
        return true;
    }

    public static void main(String[] args) {
        int[] input = StdIn.readAllInts();
        Integer[] a1 = new Integer[input.length];
        for (int i = 0; i < input.length; i++) {
            a1[i] = input[i];
        }
        sort(a1);
        assert isSorted(a1);
    }
}

選擇排序

選擇排序的過程是:找到數(shù)組中最小的那個元素叹洲,然后將它和數(shù)組中的第一個元素交換位置柠硕,如果第一個元素就是最小的元素,就和它自己交換运提。接著在剩下的元素中找到最小的元素仅叫,將它與數(shù)組的第二個元素交換位置,如此反復(fù)糙捺,直到處理完數(shù)組的所有元素。

public static void sort(Comparable[] a) {
    int minIndex = 0;
    for (int i = 0; i < a.length; i++) {
        // min = a[i];
        minIndex = i;
        for (int j = i + 1; j < a.length; j++) {
            if (less(a[j], a[minIndex])) {
                // min = a[j];
                minIndex = j;
            }
        }
        exch(a, i, minIndex);
    }
}

算法特點(diǎn)

排序算法的開銷主要包括數(shù)組元素的交換和比較兩方面笙隙。
選擇排序的交換次數(shù)為N洪灯,等于數(shù)組的規(guī)模。
選擇排序的比較次數(shù)可以從算法的執(zhí)行過程得知竟痰,外層循環(huán)N次签钩,每次排好一個元素,下一次的內(nèi)層循環(huán)的起始索引加1坏快,則比較次數(shù)減1铅檩,所以一共比較(N-1)+(N-2)+...+(1)=(N-1)*(N-2)/2次,~N^2/2

選擇排序算法的增長數(shù)量級是平方級別的莽鸿,此外這種算法還有如下特點(diǎn):

  • 運(yùn)行時間與輸入無關(guān)
    為了找出最小的元素而掃描一遍數(shù)組并不能為下一次掃描提供什么信息昧旨,所以排序隨機(jī)元素組成的數(shù)組和排序元素已經(jīng)有序的數(shù)組或元素值全部相同的數(shù)組所用的時間是一樣的。
  • 數(shù)據(jù)移動次數(shù)是所有排序算法中最少的
    選擇排序交換次數(shù)和數(shù)組的大小是線性關(guān)系祥得,隨后學(xué)習(xí)的其它排序算法都不具備這個特性兔沃,大部分的增長數(shù)量級是線性對數(shù)或者平方級別的。

插入排序

將紙牌排序時级及,一般采用的方法是一張一張來乒疏,把當(dāng)前的這張牌插入到已經(jīng)排好序的牌中的合適位置。插入排序的原理與這個類似饮焦。唯一的區(qū)別是:將一個元素插入數(shù)組中的某個位置時怕吴,這個位置之后的所有元素都需要向后移動一位窍侧。

public static void sort(Comparable[] a) {
    for (int i = 1; i < a.length; i++) {
        for (int j = i; j > 0 && less(a[j], a[j - 1]); j--) {
            exch(a, j, j - 1);
        }
    }
}

算法特點(diǎn)

插入排序所需的時間則是與輸入數(shù)組的特點(diǎn)有很大關(guān)系的,最快的時候可以在線性時間內(nèi)完成转绷,最慢的時候卻達(dá)到平方級別伟件。
最好情況既輸入本身已經(jīng)是有序的,那么外層循環(huán)會執(zhí)行N-1次暇咆,每次循環(huán)都會執(zhí)行l(wèi)ess(a[j], a[j - 1])锋爪,所以需要比較N-1次,但進(jìn)入內(nèi)層循環(huán)的條件都不會滿足爸业,則交換0次其骄。
最壞的情況則是輸入是倒序的,那么從索引=1開始扯旷,每個元素都會被移動拯爽,且每次比較都會對應(yīng)一次移動,比較與移動的次數(shù)相等钧忽。第二個元素比較1次毯炮,第三個較2次,第4個3次耸黑,...第N個N-1此桃煎,一共約N^2/2次比較,N^2/2次移動大刊;
那么在輸入元素隨機(jī)的情況下为迈,可以認(rèn)為平均每個元素都可能移動半個數(shù)組的距離,所需的比較缺菌、移動次數(shù)為最壞情況的一般葫辐,約N^2/4次比較,N^2/4次移動伴郁。
插入排序的特點(diǎn)耿战,決定了它非常適用于實(shí)際應(yīng)用中常見的部分有序的數(shù)組的排序。

希爾排序

希爾排序是對插入排序的改進(jìn)焊傅。插入排序?qū)τ陔S機(jī)輸入的增長數(shù)量級在平方級別剂陡,對于規(guī)模較大的問題其運(yùn)行時間會比較慢。因?yàn)椴迦肱判蛑粫粨Q相鄰的元素狐胎,元素只能一點(diǎn)一點(diǎn)地從當(dāng)前位置移動到其應(yīng)該呆的位置鹏倘。
希爾排序針對這一的進(jìn)行了改進(jìn),增加了元素移動的跨度顽爹。希爾排序的思想是使數(shù)組中任意間隔為h的元素都是有序的纤泵,這樣的數(shù)組被稱為h有序數(shù)組。一個h有序數(shù)組就是h個互相獨(dú)立的有序數(shù)組編織在一起組成的數(shù)組。如下所示捏题,h為2時玻褪,數(shù)組可以分為2個獨(dú)立的子數(shù)組,將這兩個子數(shù)組排序后公荧,再進(jìn)行一次排序带射,整個數(shù)組就是有序的了。

L   E   E   A   M   H   L   E  
L-------E-------M-------L      
    E-------A-------H-------E      

如果h很大循狰,則可以把移動到很遠(yuǎn)的地方窟社。希爾排序在運(yùn)行時,先使用較大的h進(jìn)行粗排绪钥,然后按照一定的規(guī)律逐步減小h灿里,當(dāng)h減小到1時,即完成了數(shù)組的最終排序程腹。這樣做有什么效果呢匣吊,多輪排序會不會反而速度更慢呢?實(shí)際上希爾排序的比插入排序快得多寸潦。這是因?yàn)橄柵判驒?quán)衡了子數(shù)組的規(guī)模和有序性色鸳,排序之處,各個子數(shù)組都很短见转,排序后期子數(shù)組又都是部分有序的命雀,插入排序在這兩種情況下都特別適合。
如下為希爾排序的實(shí)現(xiàn)斩箫,h序列選擇了最常用的3*h+1序列吏砂,即1,4,13,40,121,364,1093...

public static void sort(Comparable[] a) {
    int N = a.length;
    int h = 1;
    while (h <= N / 3) {
        h = 3 * h + 1;
    }

    while (h >= 1) {
        for (int i = h; i < N; i++) {
            for (int j = i; j > h && less(a[j], a[j - h]); j -= h) {
                exch(a, j, j - h);
            }
        }
        h /= 3;
    }
}

算法特點(diǎn)

h序列的選擇對希爾排序的性能影響很大,但透徹理解希爾排序的性能至今仍然是一項(xiàng)挑戰(zhàn)校焦,有很多論文研究了各種不同的地址序列,但都無法證明某個序列是“最好的”统倒。
可以通過比較三種算法的時間來直觀地感受不同算法的差異寨典,下面是處理10萬條int數(shù)組時的時間對比:

Selection, 37.595 s
Insertion, 76.14 s
Shell, 0.136 s

由此可見,希爾排序相比選擇排序和插入排序要高效得多房匆。對于中等大小規(guī)模的數(shù)組耸成,希爾排序的運(yùn)行時間是可接受的,其它一些更高級的算法可能只會比希爾排序快2倍浴鸿,但這些算法的代碼卻更復(fù)雜井氢。在沒有可用的系統(tǒng)排序算法可用,或者為嵌入式系統(tǒng)編寫代碼時岳链,可以考慮使用希爾排序花竞。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市掸哑,隨后出現(xiàn)的幾起案子约急,更是在濱河造成了極大的恐慌零远,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,366評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件厌蔽,死亡現(xiàn)場離奇詭異牵辣,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)奴饮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評論 3 395
  • 文/潘曉璐 我一進(jìn)店門纬向,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人戴卜,你說我怎么就攤上這事逾条。” “怎么了叉瘩?”我有些...
    開封第一講書人閱讀 165,689評論 0 356
  • 文/不壞的土叔 我叫張陵膳帕,是天一觀的道長。 經(jīng)常有香客問我薇缅,道長危彩,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,925評論 1 295
  • 正文 為了忘掉前任泳桦,我火速辦了婚禮汤徽,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘灸撰。我一直安慰自己谒府,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,942評論 6 392
  • 文/花漫 我一把揭開白布浮毯。 她就那樣靜靜地躺著完疫,像睡著了一般。 火紅的嫁衣襯著肌膚如雪债蓝。 梳的紋絲不亂的頭發(fā)上壳鹤,一...
    開封第一講書人閱讀 51,727評論 1 305
  • 那天,我揣著相機(jī)與錄音饰迹,去河邊找鬼芳誓。 笑死,一個胖子當(dāng)著我的面吹牛啊鸭,可吹牛的內(nèi)容都是我干的锹淌。 我是一名探鬼主播,決...
    沈念sama閱讀 40,447評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼赠制,長吁一口氣:“原來是場噩夢啊……” “哼赂摆!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,349評論 0 276
  • 序言:老撾萬榮一對情侶失蹤库正,失蹤者是張志新(化名)和其女友劉穎曲楚,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體褥符,經(jīng)...
    沈念sama閱讀 45,820評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡龙誊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,990評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了喷楣。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片趟大。...
    茶點(diǎn)故事閱讀 40,127評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖铣焊,靈堂內(nèi)的尸體忽然破棺而出逊朽,到底是詐尸還是另有隱情,我是刑警寧澤曲伊,帶...
    沈念sama閱讀 35,812評論 5 346
  • 正文 年R本政府宣布叽讳,位于F島的核電站,受9級特大地震影響坟募,放射性物質(zhì)發(fā)生泄漏岛蚤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,471評論 3 331
  • 文/蒙蒙 一懈糯、第九天 我趴在偏房一處隱蔽的房頂上張望涤妒。 院中可真熱鬧,春花似錦赚哗、人聲如沸她紫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽贿讹。三九已至,卻和暖如春够掠,著一層夾襖步出監(jiān)牢的瞬間民褂,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評論 1 272
  • 我被黑心中介騙來泰國打工祖屏, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留助赞,地道東北人买羞。 一個月前我還...
    沈念sama閱讀 48,388評論 3 373
  • 正文 我出身青樓袁勺,卻偏偏與公主長得像,于是被迫代替她去往敵國和親畜普。 傳聞我的和親對象是個殘疾皇子期丰,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,066評論 2 355

推薦閱讀更多精彩內(nèi)容