常見排序算法(5)--歸并排序(遞歸版)

基本思想

歸并排序(MERGE-SORT)是利用歸并的思想實(shí)現(xiàn)的排序方法撩穿,該算法采用經(jīng)典的分治(divide-and-conquer)策略(分治法將問題分(divide)成一些小的問題然后遞歸求解黄绩,而治(conquer)的階段則將分的階段得到的各答案"修補(bǔ)"在一起,即分而治之)蚜退。

分而治之

可以看到這種結(jié)構(gòu)很像一棵完全二叉樹,本文的歸并排序我們采用遞歸去實(shí)現(xiàn)(也可采用迭代的方式去實(shí)現(xiàn))利耍。分階段可以理解為就是遞歸拆分子序列的過程望抽,遞歸深度為log2n。

合并相鄰有序子序列

再來看看階段煌妈,我們需要將兩個(gè)已經(jīng)有序的子序列合并成一個(gè)有序序列儡羔,比如上圖中的最后一次合并,要將[4,5,7,8]和[1,2,3,6]兩個(gè)已經(jīng)有序的子序列璧诵,合并為最終序列[1,2,3,4,5,6,7,8]汰蜘,來看下實(shí)現(xiàn)步驟。


"治" 代碼實(shí)現(xiàn)

圖看完了之宿,現(xiàn)在來看代碼吧族操。

void merge(int *arr, int left, int mid, int right ,int *temp)
{
    int i = left;//左序列指針
    int j = mid+1;//右序列指針
    int t = 0;//臨時(shí)數(shù)組指針

    while (( i <= mid) && ( j <= right))
    {
        if (arr[i] < arr[j])
        {
            temp[t++] = arr[i++];
        }
        else
        {
            temp[t++] = arr[j++];
        }
    }
    while (i <= mid)//將左邊剩余元素填充進(jìn)temp中
    {
        temp[t++] = arr[i++];
    }
    while (j <= right)//將右序列剩余元素填充進(jìn)temp中
    {
        temp[t++] = arr[j++];
    }
    t = 0;
    //將temp中的元素全部拷貝到原數(shù)組中
    while (left <= right)
    {
        arr[left++] = temp[t++];
    }
}

這個(gè)函數(shù)有點(diǎn)難理解,我們還是拿上圖的具體例子來說吧比被。執(zhí)行merge(arr, 0, 4, 8, temp)色难,其實(shí)就是把{4,5,7,8}(暫時(shí)稱為左子數(shù)組)和{1,2,3,6}(右子數(shù)組)兩個(gè)已經(jīng)有序的子序列炕婶,合并為最終序列{1,2,3,4,5,6,7,8}。先比較左右子數(shù)組的第一個(gè)元素的大小莱预,把較小的存到臨時(shí)數(shù)組的第一個(gè)元素柠掂,然后把對應(yīng)的子數(shù)組的指針加1,繼續(xù)比較依沮。直到左右子數(shù)組中某一個(gè)子數(shù)組完全被復(fù)制到了temp中涯贞,接下來的while循環(huán)做的事情就是把剩下的子數(shù)組中的剩余元素都復(fù)制進(jìn)temp。由于不知道是左子數(shù)組還是右子數(shù)組剩余元素危喉,所以都要寫一遍宋渔。最后把temp數(shù)組的元素拷貝到arr中,arr就排序好了辜限。

"分" 代碼實(shí)現(xiàn)
void MSort(int *arr, int left, int right, int *temp)
{
    // if (left = right) return; 
    if (left < right)
    {
        int mid = (left + right) / 2;
        MSort(arr, left, mid, temp);//左邊歸并排序皇拣,使得左子序列有序
        MSort(arr, mid+1, right, temp);//右邊歸并排序,使得右子序列有序
        merge(arr, left, mid, right, temp);//將兩個(gè)有序子數(shù)組合并操作
    }
}

"分"采用了遞歸的方法薄嫡,采用了折半的策略氧急,先歸并左子數(shù)組,再歸并右子數(shù)組毫深,再把左右子數(shù)組合并吩坝。有的讀者可能覺得MSort函數(shù)沒有終止條件,其實(shí)它是有的哑蔫,隱含的條件是這個(gè)if (left = right) return;钉寝,因?yàn)楫?dāng)left = right時(shí),其實(shí)只有一個(gè)元素闸迷,肯定是有序的嵌纲。

歸并排序遞歸版 代碼實(shí)現(xiàn)
// 歸并排序遞歸版
void MergeSort(int *arr, int length)
{
    int *temp = (int *)malloc(sizeof(int) * length);//在排序前,先建好一個(gè)長度等于原數(shù)組長度的臨時(shí)數(shù)組腥沽,避免遞歸中頻繁開辟空間
    MSort(arr, 0, length-1, temp);
    free(temp);
}

歸并排序是穩(wěn)定排序逮走,它也是一種十分高效的排序,能利用完全二叉樹特性的排序一般性能都不會太差巡球。從上文的圖中可看出言沐,每次合并操作的平均時(shí)間復(fù)雜度為O(n)邓嘹,而完全二叉樹的深度為|log2n|酣栈。總的平均時(shí)間復(fù)雜度為O(nlogn)汹押。而且矿筝,歸并排序的最好,最壞棚贾,平均時(shí)間復(fù)雜度均為O(nlogn)窖维。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末榆综,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子铸史,更是在濱河造成了極大的恐慌鼻疮,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,451評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件琳轿,死亡現(xiàn)場離奇詭異判沟,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)崭篡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評論 3 394
  • 文/潘曉璐 我一進(jìn)店門挪哄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人琉闪,你說我怎么就攤上這事迹炼。” “怎么了颠毙?”我有些...
    開封第一講書人閱讀 164,782評論 0 354
  • 文/不壞的土叔 我叫張陵斯入,是天一觀的道長。 經(jīng)常有香客問我蛀蜜,道長咱扣,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,709評論 1 294
  • 正文 為了忘掉前任涵防,我火速辦了婚禮闹伪,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘壮池。我一直安慰自己偏瓤,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,733評論 6 392
  • 文/花漫 我一把揭開白布椰憋。 她就那樣靜靜地躺著厅克,像睡著了一般。 火紅的嫁衣襯著肌膚如雪橙依。 梳的紋絲不亂的頭發(fā)上证舟,一...
    開封第一講書人閱讀 51,578評論 1 305
  • 那天,我揣著相機(jī)與錄音窗骑,去河邊找鬼女责。 笑死,一個(gè)胖子當(dāng)著我的面吹牛创译,可吹牛的內(nèi)容都是我干的抵知。 我是一名探鬼主播,決...
    沈念sama閱讀 40,320評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼刷喜!你這毒婦竟也來了残制?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,241評論 0 276
  • 序言:老撾萬榮一對情侶失蹤掖疮,失蹤者是張志新(化名)和其女友劉穎初茶,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體浊闪,經(jīng)...
    沈念sama閱讀 45,686評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡纺蛆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,878評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了规揪。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片桥氏。...
    茶點(diǎn)故事閱讀 39,992評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖猛铅,靈堂內(nèi)的尸體忽然破棺而出字支,到底是詐尸還是另有隱情,我是刑警寧澤奸忽,帶...
    沈念sama閱讀 35,715評論 5 346
  • 正文 年R本政府宣布堕伪,位于F島的核電站,受9級特大地震影響栗菜,放射性物質(zhì)發(fā)生泄漏欠雌。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,336評論 3 330
  • 文/蒙蒙 一疙筹、第九天 我趴在偏房一處隱蔽的房頂上張望富俄。 院中可真熱鬧,春花似錦而咆、人聲如沸霍比。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽悠瞬。三九已至,卻和暖如春涯捻,著一層夾襖步出監(jiān)牢的瞬間浅妆,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評論 1 270
  • 我被黑心中介騙來泰國打工障癌, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留凌外,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,173評論 3 370
  • 正文 我出身青樓混弥,卻偏偏與公主長得像趴乡,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子蝗拿,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,947評論 2 355

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

  • 概述 排序有內(nèi)部排序和外部排序晾捏,內(nèi)部排序是數(shù)據(jù)記錄在內(nèi)存中進(jìn)行排序,而外部排序是因排序的數(shù)據(jù)很大哀托,一次不能容納全部...
    蟻前閱讀 5,186評論 0 52
  • 通過前面的知識惦辛,我們已經(jīng)知道,有序的數(shù)據(jù)在查找時(shí)有極大的性能提升仓手。很多查找都基于有序數(shù)據(jù)胖齐,但并不是所有的結(jié)構(gòu)都能像...
    大大紙飛機(jī)閱讀 1,173評論 0 1
  • 概述 因?yàn)榻⊥由蠈Ω鞣N排序算法理解不深刻嗽冒,過段時(shí)間面對排序就蒙了呀伙。所以決定對我們常見的這幾種排序算法進(jìn)行統(tǒng)一總...
    清風(fēng)之心閱讀 700評論 0 1
  • 一、直接插入排序 直接插入排序(Insertion Sort)的基本思想是:每次將一個(gè)待排序的元素記錄添坊,按其關(guān)鍵字...
    kevin16929閱讀 558評論 0 0
  • 1.插入排序—直接插入排序(Straight Insertion Sort) 基本思想: 將一個(gè)記錄插入到已排序好...
    依依玖玥閱讀 1,258評論 0 2