005 堆排序(二)原地堆排序

原地堆排序思想

  • 對于已經(jīng)“堆化”的數(shù)據(jù),堆頂?shù)脑厥亲畲蟮慕徘蹋瑢?yīng)到數(shù)組就是數(shù)組的第一個元素是最大的绍哎,原地的堆排序就是以這個性質(zhì)作為出發(fā)點的;
  • 將堆頂元素和最后一個元素交換崇堰,最大的元素就歸位了;
  • 對新?lián)Q到堆頂?shù)脑刈鱿鲁敛僮鞣庇ǎ蛊渎湓诙训暮线m位置特幔,此時除了已歸位到數(shù)組最后的“大家伙”們,整個數(shù)組還是滿足堆的性質(zhì)的蚯斯;
  • 繼續(xù)對堆頂?shù)脑睾同F(xiàn)存的未歸位序列的最后一個元素交換;

算法實現(xiàn)

  • 先對待排序的數(shù)組heapify遭赂;
  • 再拿堆頂元素和最后一個元素換横辆,換上堆頂?shù)脑刈鰝€下沉操作;
// 不使用一個額外的最大堆, 直接在原數(shù)組上進行原地的堆排序
public class HeapSort {

    // 我們的算法類不允許產(chǎn)生任何實例
    private HeapSort(){}

    public static void sort(Comparable[] arr){

        int n = arr.length;

        // 注意狈蚤,此時我們的堆是從0開始索引的
        // 從(最后一個元素的索引-1)/2開始
        // 最后一個元素的索引 = n-1
        for( int i = (n-1-1)/2 ; i >= 0 ; i -- )
            shiftDown(arr, n, i);

        for( int i = n-1; i > 0 ; i-- ){
            swap(arr, 0, i);
            shiftDown(arr, i, 0);
        }
    }

    // 交換堆中索引為i和j的兩個元素
    private static void swap(Object[] arr, int i, int j){
        Object t = arr[i];
        arr[i] = arr[j];
        arr[j] = t;
    }

    // 原始的shiftDown過程
    private static void shiftDown(Comparable[] arr, int n, int k){

        while( 2*k+1 < n ){
            int j = 2*k+1;
            if( j+1 < n && arr[j+1].compareTo(arr[j]) > 0 )
                j += 1;

            if( arr[k].compareTo(arr[j]) >= 0 )break;

            swap( arr, k, j);
            k = j;
        }
    }

    // 優(yōu)化的shiftDown過程, 使用賦值的方式取代不斷的swap,
    // 該優(yōu)化思想和我們之前對插入排序進行優(yōu)化的思路是一致的
    private static void shiftDown2(Comparable[] arr, int n, int k){

        Comparable e = arr[k];
        while( 2*k+1 < n ){
            int j = 2*k+1;
            if( j+1 < n && arr[j+1].compareTo(arr[j]) > 0 )
                j += 1;

            if( e.compareTo(arr[j]) >= 0 )
                break;

            arr[k] = arr[j];
            k = j;
        }

        arr[k] = e;
    }

    // 測試 HeapSort
    public static void main(String[] args) {

        int N = 1000000;
        Integer[] arr = SortTestHelper.generateRandomArray(N, 0, 100000);
        SortTestHelper.testSort("_04.HeapSort", arr);

        return;
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末脆侮,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子蹋绽,更是在濱河造成了極大的恐慌筋蓖,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蚣抗,死亡現(xiàn)場離奇詭異,居然都是意外死亡翰铡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進店門例证,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人织咧,你說我怎么就攤上這事漠秋。” “怎么了庆锦?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵搂抒,是天一觀的道長绿渣。 經(jīng)常有香客問我燕耿,道長,這世上最難降的妖魔是什么淀散? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任蚜锨,我火速辦了婚禮,結(jié)果婚禮上亚再,老公的妹妹穿的比我還像新娘。我一直安慰自己氛悬,他們只是感情好,可當我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布棍现。 她就那樣靜靜地躺著镜遣,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上娄柳,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天艘绍,我揣著相機與錄音,去河邊找鬼鞍盗。 笑死跳昼,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的鹅颊。 我是一名探鬼主播,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼锚烦,長吁一口氣:“原來是場噩夢啊……” “哼帝雇!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起尸闸,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎苞尝,沒想到半個月后宦芦,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體宙址,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡抡砂,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年恬涧,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片气破。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖低匙,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情顽冶,我是刑警寧澤,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布绞呈,位于F島的核電站,受9級特大地震影響佃声,放射性物質(zhì)發(fā)生泄漏倘要。R本人自食惡果不足惜圾亏,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一志鹃、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧曹铃,春花似錦、人聲如沸陕见。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽非竿。三九已至,卻和暖如春红柱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背韧骗。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工零聚, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留袍暴,地道東北人。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓岗宣,卻偏偏與公主長得像淋样,于是被迫代替她去往敵國和親耗式。 傳聞我的和親對象是個殘疾皇子趁猴,可洞房花燭夜當晚...
    茶點故事閱讀 44,927評論 2 355