堆排序

概念

??????堆是具有以下性質(zhì)的完全二叉樹:每個(gè)節(jié)點(diǎn)的值都要大于或等于其左右孩子的值员萍,稱為大頂堆襟铭;或者每個(gè)節(jié)點(diǎn)的值都小于其左右孩子節(jié)點(diǎn)的值贱鄙,稱為小頂堆。

性質(zhì)(完全二叉樹的性質(zhì))

??????如果對一棵有n個(gè)節(jié)點(diǎn)的完全二叉樹(其深度為logn + 1)的節(jié)點(diǎn)按層次編號(hào)(從第1層到第logn + 1 層潮罪,每層從左到右)康谆,對任一節(jié)點(diǎn)i(1 ≤ i ≤ n)有:

  • 如果i=1,則節(jié)點(diǎn)i是二叉樹的根嫉到,無雙親沃暗;如果i > 1,則其雙親是節(jié)點(diǎn) i / 2 何恶。
  • 如果2i > n孽锥,則節(jié)點(diǎn) i 無左孩子(i為葉子節(jié)點(diǎn));否則其左孩子就是節(jié)點(diǎn)2i 导而。
  • 如果 2i+1 > n忱叭,則節(jié)點(diǎn) i 無右孩子隔崎;否則其右孩子就是 2i+1 今艺。

如果將上圖所示的大頂堆和小頂堆用層次遍歷存入數(shù)組,則如下圖所示:


基本思想

??????堆排序就是利用堆進(jìn)行排序的方法(利用大頂堆完成從小到大的排序爵卒,利用小頂堆完成從大到小的排序)虚缎。其基本思想是,將待排序的序列構(gòu)造成一個(gè)大頂堆,此時(shí)整個(gè)序列的最大值就是堆頂?shù)母?jié)點(diǎn)实牡,將它一走(其實(shí)就是將其與數(shù)組的末尾元素交換陌僵,此時(shí)末尾元素就是最大值),然后將剩余的n-1個(gè)序列重新構(gòu)造成一個(gè)堆创坞,就會(huì)得到n個(gè)元素中的次小值碗短。如此反復(fù)進(jìn)行,就可以得到一個(gè)有序序列题涨。(堆排序相當(dāng)于簡單排序算法的升級(jí)偎谁,同屬于 選擇排序類

堆調(diào)整函數(shù)-heapAdjust

    // 已知array[start~end]中記錄的關(guān)鍵字,除array[start]外均滿足堆的定義
    // 本函數(shù)用來調(diào)整array[start]關(guān)鍵字纲堵,使array[start~end]成為一個(gè)新的大頂堆
    void heapAdjust(int[] array, int start, int end) {
        int tmp = array[start];
        // i*2+1是i的左子節(jié)點(diǎn)
        for (int i = start * 2 + 1; i < end; i = i * 2 + 1) {
            // 選擇關(guān)鍵字較大的孩子節(jié)點(diǎn)
            if (i < end - 1 && array[i] < array[i + 1]) {
                i++;
            }
            // 若該元素大于子節(jié)點(diǎn)中較大的元素巡雨,那么他就應(yīng)該在此位置
            if (tmp > array[i]) {
                break;
            }
            // 父節(jié)點(diǎn)的位置應(yīng)該放置較大的元素
            array[start] = array[i];
            // 記錄原始start的元素應(yīng)該存放的位置
            start = i;
        }
        array[start] = tmp;
    }

堆排序算法

??????堆排序算法的實(shí)現(xiàn)包括兩個(gè)問題:1、如何由一個(gè)無序序列構(gòu)造一個(gè)堆席函;2铐望、如何在輸出堆頂元素后調(diào)整剩余的元素稱為一個(gè)新的堆

    void heapSort(int[] array) {
        int length = array.length;
        // 構(gòu)造一個(gè)大頂堆
        for (int i = length/2-1; i >= 0; i--) {
            heapAdjust(array, i, length);
        }
        for (int i = length - 1; i > 0; i--) {
            swap(array, 0, i);
            // 重新調(diào)整為大頂堆
            heapAdjust(array, 0, i - 1);
        }
    }

此處構(gòu)造大頂堆時(shí)從length/2-1開始是因?yàn)楹罄m(xù)的節(jié)點(diǎn)都是葉子節(jié)點(diǎn),這里所謂的將待排序的序列構(gòu)建成大頂堆其實(shí)就是從下往上茂附,從右到左將每個(gè)非終端節(jié)點(diǎn)當(dāng)作根節(jié)點(diǎn)正蛙,將其和其子樹調(diào)整成大頂堆。

堆排序算法的時(shí)間復(fù)雜度分析

??????堆排序的運(yùn)行時(shí)間主要消耗在初始構(gòu)建堆和在重建堆時(shí)的反復(fù)篩選上营曼。
??????在構(gòu)建堆的過程中因?yàn)槭峭耆鏄鋸淖钕聦幼钣疫叺姆墙K端節(jié)點(diǎn)開始構(gòu)建跟畅,將它與其孩子進(jìn)行比較和若有必要的交換,對于每個(gè)非終端節(jié)點(diǎn)來說溶推,其實(shí)最多進(jìn)行兩次比較和交換操作徊件,因此整個(gè)構(gòu)建過程的時(shí)間復(fù)雜度為O(n)
??????在正式排序時(shí),第i次取堆頂記錄重建堆時(shí)需要O(log i)的時(shí)間(完全二叉樹的某個(gè)節(jié)點(diǎn)到根節(jié)點(diǎn)的距離為log i + 1)蒜危,并且需要取n-1次堆頂記錄虱痕,因此重建堆的時(shí)間復(fù)雜度為O(nlogn)
??????總體來說,堆排序的時(shí)間復(fù)雜度為O(nlogn)辐赞。由于堆排序?qū)υ加涗浀呐判驙顟B(tài)并不敏感部翘,故無論最好最壞和平均狀態(tài)均為O(nlogn)。

由于初始構(gòu)建堆所需的比較次數(shù)較多响委,所以它并不適合待排序序列的個(gè)數(shù)較少的情況

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末新思,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子赘风,更是在濱河造成了極大的恐慌夹囚,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,470評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件邀窃,死亡現(xiàn)場離奇詭異荸哟,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門鞍历,熙熙樓的掌柜王于貴愁眉苦臉地迎上來舵抹,“玉大人,你說我怎么就攤上這事劣砍【逵迹” “怎么了?”我有些...
    開封第一講書人閱讀 162,577評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵刑枝,是天一觀的道長赊淑。 經(jīng)常有香客問我,道長仅讽,這世上最難降的妖魔是什么陶缺? 我笑而不...
    開封第一講書人閱讀 58,176評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮洁灵,結(jié)果婚禮上饱岸,老公的妹妹穿的比我還像新娘。我一直安慰自己徽千,他們只是感情好苫费,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著双抽,像睡著了一般百框。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上牍汹,一...
    開封第一講書人閱讀 51,155評(píng)論 1 299
  • 那天铐维,我揣著相機(jī)與錄音,去河邊找鬼慎菲。 笑死嫁蛇,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的露该。 我是一名探鬼主播睬棚,決...
    沈念sama閱讀 40,041評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼解幼!你這毒婦竟也來了抑党?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,903評(píng)論 0 274
  • 序言:老撾萬榮一對情侶失蹤撵摆,失蹤者是張志新(化名)和其女友劉穎底靠,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體台汇,經(jīng)...
    沈念sama閱讀 45,319評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡苛骨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評(píng)論 2 332
  • 正文 我和宋清朗相戀三年篱瞎,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了苟呐。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片痒芝。...
    茶點(diǎn)故事閱讀 39,703評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖牵素,靈堂內(nèi)的尸體忽然破棺而出严衬,到底是詐尸還是另有隱情,我是刑警寧澤笆呆,帶...
    沈念sama閱讀 35,417評(píng)論 5 343
  • 正文 年R本政府宣布请琳,位于F島的核電站,受9級(jí)特大地震影響赠幕,放射性物質(zhì)發(fā)生泄漏俄精。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評(píng)論 3 325
  • 文/蒙蒙 一榕堰、第九天 我趴在偏房一處隱蔽的房頂上張望竖慧。 院中可真熱鬧,春花似錦逆屡、人聲如沸圾旨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽砍的。三九已至,卻和暖如春莺治,著一層夾襖步出監(jiān)牢的瞬間廓鞠,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評(píng)論 1 269
  • 我被黑心中介騙來泰國打工谣旁, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留诫惭,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,711評(píng)論 2 368
  • 正文 我出身青樓蔓挖,卻偏偏與公主長得像夕土,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子瘟判,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評(píng)論 2 353