詳解排序算法--堆排序

選擇排序

選擇排序(Selection sort)是一種簡單直觀的排序算法丢氢。它的工作原理如下。首先在未排序序列中找到最邢雀摹(大)元素疚察,存放到排序序列的起始位置,然后仇奶,再從剩余未排序元素中繼續(xù)尋找最忻驳铡(大)元素,然后放到已排序序列的末尾该溯。以此類推岛抄,直到所有元素均排序完畢。
選擇排序的主要優(yōu)點與數(shù)據(jù)移動有關(guān)狈茉。如果某個元素位于正確的最終位置上夫椭,則它不會被移動。選擇排序每次交換一對元素论皆,它們當(dāng)中至少有一個將被移到其最終位置上益楼,因此對n個元素的表進(jìn)行排序總共進(jìn)行至多n-1次交換。在所有的完全依靠交換去移動元素的排序方法中点晴,選擇排序?qū)儆诜浅:玫囊环N。

![Uploading Selection_sort_animation_154868.gif . . .]
Selection_sort_animation.gif
  • 最壞時間復(fù)雜度 О(n2)
  • 最優(yōu)時間復(fù)雜度 О(n2)
  • 平均時間復(fù)雜度 О(n2)
  • 空間復(fù)雜度 О(n) total, O(1) auxiliary

Java實現(xiàn):


package cc;

public class Select {

    public static void selectSort(int[] a) 
    {
        int N = a.length;
        for(int i=0;i<N;i++)
        {
            /* 從A[i]到A[N–1]中找最小元悯周,并將其位置賦給MinPosition */
            int min = i;
            for(int j=i+1;j<N;j++)
            {
                if(a[j]<a[min])
                    min=j;
            }
            /* 將未排序部分的最小元換到有序部分的最后位置 */
            int t = a[i];
            a[i] = a[min];
            a[min] = t;
        }
    }
}

想要進(jìn)一步改進(jìn)選擇排序粒督,就在于

如何快速找到最小元?禽翼?屠橄?

如果讀者已經(jīng)對于堆較為熟悉的話,很容易就想到這里可以利用堆實現(xiàn)闰挡。
這就是堆排序的由來

堆排序

堆排序(Heapsort)是指利用這種數(shù)據(jù)結(jié)構(gòu)所設(shè)計的一種排序算法锐墙。堆積是一個近似完全二叉樹的結(jié)構(gòu),并同時滿足堆積的性質(zhì):即子結(jié)點的鍵值或索引總是小于(或者大于)它的父節(jié)點长酗。

堆節(jié)點的訪問

通常堆是通過一維數(shù)組來實現(xiàn)的溪北。在數(shù)組起始位置為0的情形中:

  • 父節(jié)點i的左子節(jié)點在位置(2*i+1);
  • 父節(jié)點i的右子節(jié)點在位置(2*i+2);
  • 子節(jié)點i的父節(jié)點在位置floor((i-1)/2);

堆的操作

在堆的數(shù)據(jù)結(jié)構(gòu)中,堆中的最大值總是位于根節(jié)點(在優(yōu)先隊列中使用堆的話堆中的最小值位于根節(jié)點)。堆中定義以下幾種操作:

  • 最大堆調(diào)整(Max_Heapify):將堆的末端子節(jié)點作調(diào)整之拨,使得子節(jié)點永遠(yuǎn)小于父節(jié)點
  • 創(chuàng)建最大堆(Build_Max_Heap):將堆所有數(shù)據(jù)重新排序
  • 堆排序(HeapSort):移除位在第一個數(shù)據(jù)的根節(jié)點茉继,并做最大堆調(diào)整的遞歸運算

按照選擇排序的思想,我們先實現(xiàn)一個簡單的堆排序

void Heap_Sort ( ElementType A[], int N )
{ BuildHeap(A); /* O(N) */
for ( i=0; i<N; i++ )
TmpA[i] = DeleteMin(A); /* O(logN) */
for ( i=0; i<N; i++ ) /* O(N) */
A[i] = TmpA[i];
}

T ( N ) = O ( N log N )
缺點在于:
需要額外O(N)空間蚀乔,并且復(fù)制元素需要時間烁竭。

原地堆排序

基于以上相關(guān)的操作,我們可以很容易的定義堆排序吉挣。例如派撕,假設(shè)我們已經(jīng)讀入一系列數(shù)據(jù)并創(chuàng)建了一個堆,一個最直觀的算法就是反復(fù)的調(diào)用del_max()
函數(shù)睬魂,因為該函數(shù)總是能夠返回堆中最大的值腥刹,然后把它從堆中刪除,從而對這一系列返回值的輸出就得到了該序列的降序排列汉买。

真正的原地堆排序使用了另外一個小技巧衔峰。堆排序的過程是:

  • 創(chuàng)建一個堆H[0..n-1]
  • 把堆首(最大值)和堆尾互換
  • 把堆的尺寸縮小1,并調(diào)用shift_down(0),目的是把新的數(shù)組頂端數(shù)據(jù)調(diào)整到相應(yīng)位置
  • 重復(fù)步驟2蛙粘,直到堆的尺寸為1

偽碼

void Heap_Sort ( ElementType A[], int N )
{ for ( i=N/2-1; i>=0; i-- )/* BuildHeap */
PercDown( A, i, N );
for ( i=N-1; i>0; i-- ) {
Swap( &A[0], &A[i] ); /* DeleteMax */
PercDown( A, 0, i );
}
}
  • 最壞時間復(fù)雜度
O(n\log n)
O(n\log n)
  • 最優(yōu)時間復(fù)雜度

O(n\log n)
O(n\log n)
[1]

  • 平均時間復(fù)雜度
\Theta (n\log n)
\Theta (n\log n)
  • 堆排序的動態(tài)圖


    Sorting_heapsort_anim.gif

Java實現(xiàn)

package cc;

public class HeapSort {
    
    private static int leftChild(int i) {
        return 2*i+1;
    }
    
    private static void percDown(int[] a, int i, int n) {
        int child;
        int temp;
        
        for(temp = a[i]; leftChild(i) < n;i = child) {
            child = leftChild(i);
            if(child != n-1 && a[child] < a[child+1])
                child++;
            if(temp < a[child])
                a[i] = a[child];
            else
                break;
        }
        a[i] = temp;
    }

    public static void heapsort(int[] a) {
        
        for(int i=a.length/2-1;i>=0;i--) {
            percDown(a, i, a.length);
        }
        
        for(int i=a.length-1;i>0;i--) {
            swap(a, 0, i);
            percDown(a, 0, i);
        }
    }
    
    private static void swap(int[] a, int i, int j) {
        
        int temp = a[i];
        a[i] = a[j];
        a[j] = temp;
        
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末垫卤,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子出牧,更是在濱河造成了極大的恐慌穴肘,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件舔痕,死亡現(xiàn)場離奇詭異评抚,居然都是意外死亡,警方通過查閱死者的電腦和手機伯复,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進(jìn)店門慨代,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人啸如,你說我怎么就攤上這事侍匙。” “怎么了叮雳?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵想暗,是天一觀的道長。 經(jīng)常有香客問我帘不,道長说莫,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任寞焙,我火速辦了婚禮储狭,結(jié)果婚禮上互婿,老公的妹妹穿的比我還像新娘。我一直安慰自己晶密,他們只是感情好擒悬,可當(dāng)我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著稻艰,像睡著了一般懂牧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上尊勿,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天僧凤,我揣著相機與錄音,去河邊找鬼元扔。 笑死躯保,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的澎语。 我是一名探鬼主播途事,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼擅羞!你這毒婦竟也來了尸变?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤减俏,失蹤者是張志新(化名)和其女友劉穎召烂,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體娃承,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡奏夫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了历筝。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片酗昼。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖漫谷,靈堂內(nèi)的尸體忽然破棺而出仔雷,到底是詐尸還是另有隱情,我是刑警寧澤舔示,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站电抚,受9級特大地震影響惕稻,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蝙叛,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一俺祠、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦蜘渣、人聲如沸淌铐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽腿准。三九已至,卻和暖如春拾碌,著一層夾襖步出監(jiān)牢的瞬間吐葱,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工校翔, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留弟跑,地道東北人。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓防症,卻偏偏與公主長得像孟辑,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子蔫敲,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,786評論 2 345

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

  • 概述 排序有內(nèi)部排序和外部排序饲嗽,內(nèi)部排序是數(shù)據(jù)記錄在內(nèi)存中進(jìn)行排序,而外部排序是因排序的數(shù)據(jù)很大燕偶,一次不能容納全部...
    蟻前閱讀 5,164評論 0 52
  • 概述:排序有內(nèi)部排序和外部排序喝噪,內(nèi)部排序是數(shù)據(jù)記錄在內(nèi)存中進(jìn)行排序,而外部排序是因排序的數(shù)據(jù)很大指么,一次不能容納全部...
    每天刷兩次牙閱讀 3,727評論 0 15
  • 1.插入排序—直接插入排序(Straight Insertion Sort) 基本思想: 將一個記錄插入到已排序好...
    依依玖玥閱讀 1,239評論 0 2
  • 微信又更新了酝惧,它越來越久的侵入我們的生活,朋友慢慢的只剩個圈了伯诬,認(rèn)識的不認(rèn)識的晚唇,游戲里的npc殺一下還需要打好幾下...
    木箱子閱讀 258評論 0 0
  • 中學(xué)時期經(jīng)朋友介紹有幸與中國玉雕大師麥少懷相識。在啟蒙老師麥少懷的悉心指導(dǎo)下對玉雕藝術(shù)有了新的認(rèn)識盗似,從此對翡翠藝術(shù)...
    Culbol珂洛泊閱讀 1,500評論 0 2