算法基礎(chǔ)--遞歸入門の歸并排序

本文只是自己的筆記砚著,并不具備過多的指導(dǎo)意義。

為了理解很多都使用了遞歸茅撞,而不是自己通過while進(jìn)行壓棧處理帆卓。
代碼的初衷是便于理解,網(wǎng)上大神優(yōu)化過的代碼很多米丘,也不建議在項(xiàng)目中copy本文代碼剑令。

目錄

  • 歸并排序
    • 如何合并兩個(gè)有序數(shù)組
    • 使兩端分別有序
    • 最外側(cè)還有一個(gè)入口方法
    • 圖解排序過程
  • 遞歸時(shí)間復(fù)雜度的估算
    • master公式

歸并排序

眾所周知,分治策略中使用遞歸來求解問題分為三步走拄查,分別為分解吁津、解決和合并。

所以歸并排序中心思想是通過二分的方式堕扶,將一個(gè)段數(shù)組拆分成左右兩端碍脏,然后進(jìn)行合并

  • 如何合并兩個(gè)有序數(shù)組

通過將最小值依次外排的方式梭依,進(jìn)行合并

  1. 兩個(gè)指針p1p2指向兩個(gè)數(shù)組的首位置典尾,每次將較小的值外排進(jìn)輔助數(shù)組并且右移指針役拴。
  2. 當(dāng)一個(gè)指針越界后,將另一個(gè)剩余的元素放入輔助數(shù)組钾埂。
  3. 最后的輔助數(shù)組將是一個(gè)有序數(shù)組河闰。
/// 對(duì)一個(gè)數(shù)組的兩個(gè)有序分段進(jìn)行整合排序
///
/// - Parameters:
///   - arr: 數(shù)組
///   - left: 左側(cè)起點(diǎn)
///   - mid: 中心點(diǎn),左側(cè)末尾
///   - right: 右側(cè)末尾
func merge(arr: inout [Int] ,left: Int ,mid: Int ,right:Int) {
    
    var help : [Int] = [Int](repeating: 0, count: right-left+1) //輔助數(shù)組
    var p1 = left//左側(cè)指針
    var p2 = mid+1 //右側(cè)指針
    var i = 0 //容器指針位置
    
    while p1<=mid && p2<=right {
        if arr[p1] <= arr[p2] {//左側(cè)指針位置小于等于右側(cè)指針位置
            help[i] = arr[p1] //將左側(cè)指針位置放入輔助數(shù)組
            p1 = p1+1 //左側(cè)指針右移
        }else {//右側(cè)指針大于左側(cè)指針位置
            help[i] = arr[p2] //將右側(cè)指針位置放入輔助數(shù)組
            p2 = p2+1 //左側(cè)指針右移
        }
        i = i+1  //容器指針右移
    }
    
    //到這里褥紫,p1,p2之中已經(jīng)有一個(gè)指針越界了
    //沒有越界的那個(gè)淤击,重復(fù)上面的操作寫入輔助數(shù)組
    while p1<=mid {
        help[i] = arr[p1]
        p1 = p1+1
        i = i+1
    }
    while p2<=right {
        help[i] = arr[p2]
        p2 = p2+1
        i = i+1
    }
    //寫入完畢,用輔助數(shù)組替換進(jìn)原數(shù)組
    i = 0
    for index in left...right { //left,left+1...right-1,right
        arr[index] = help[i]
        i = i+1
    }
}

之所以先說這個(gè)故源,是因?yàn)檫@個(gè)方法是核心方法,并且寫完滯后直接將可以測(cè)試汞贸。
測(cè)試通過之后绳军,再去測(cè)試下面的遞歸方法可以更加準(zhǔn)確的確定問題所在。

  • 使兩端分別有序

通過遞歸的方式矢腻,將長(zhǎng)數(shù)組最終分解成有序的數(shù)組進(jìn)行排序處理门驾。

比如[4,2,6,1,9,7]

/// 在一個(gè)數(shù)組的某一段上進(jìn)行排序
///
/// - Parameters:
///   - arr: 數(shù)組
///   - left: 左側(cè)
///   - right: 右側(cè)
func mergeProcess(arr: inout [Int] ,left: Int ,right:Int) {
    
    if left==right { //左右相等,說明這次要調(diào)整的只有一個(gè)數(shù)
        return
    }
    
    let mid = (left+right)/2 //取得中心點(diǎn)位置
    mergeProcess(arr: &arr, left: left, right: mid)//對(duì)左半邊進(jìn)行排序
    mergeProcess(arr: &arr, left: mid+1, right: right)//對(duì)右半邊進(jìn)行排序
    //此時(shí)左右兩側(cè)都已經(jīng)排序完成
    merge(arr: &arr, left: left, mid: mid, right: right)//對(duì)左右兩側(cè)進(jìn)行合并排序
}
  • 最外側(cè)還有一個(gè)入口方法
/// 歸并排序
///
/// - Parameter arr: 數(shù)組
func mergeSort(arr: inout [Int]) {
    if arr.count<2 {
        return
    }
    mergeProcess(arr: &arr, left: 0, right: arr.count-1)
}

時(shí)間復(fù)雜度O(N * logN)多柑,額外空間復(fù)雜度O(N)奶是。

  • 圖解排序過程

網(wǎng)上還看到一個(gè)動(dòng)圖,結(jié)合上面的應(yīng)該更容易理解了竣灌。

這個(gè)過程中聂沙,不管數(shù)組多長(zhǎng),最后都將被劃分成2個(gè)單位長(zhǎng)度的數(shù)組進(jìn)行排序初嘹。
然后向上依次合并并且排序及汉。

這也很好的體現(xiàn)出了分治或者遞歸的思想所在,將大樣本劃分成小樣本并依次解決屯烦。


遞歸時(shí)間復(fù)雜度的估算

只說一種普遍的通用情況

  • master公式
T(N) = A*T(N/B) + O(N^D)

當(dāng)量本量為N的情況下坷随,整個(gè)樣本被劃分成B樣本量,共執(zhí)行A次驻龟。
出去調(diào)用遞歸過程之外温眉,剩下的部分的時(shí)間復(fù)雜度O(N^D)

1) log(b,a) > d -> 復(fù)雜度為O(N^log(b,a)) 
2) log(b,a) = d -> 復(fù)雜度為O(N^d * logN) 
3) log(b,a) < d -> 復(fù)雜度為O(N^d)

以歸并排序?yàn)槔?

func mergeProcess(arr: inout [Int] ,left: Int ,right:Int) {
    
    if left==right { //左右相等,說明這次要調(diào)整的只有一個(gè)數(shù)
        return
    }
    
    let mid = (left+right)/2 //取得中心點(diǎn)位置
    mergeProcess(arr: &arr, left: left, right: mid)//T(N/2)
    mergeProcess(arr: &arr, left: mid+1, right: right)//T(N/2)
  
    merge(arr: &arr, left: left, mid: mid, right: right)//O(N)
}

T(N) = T(N/2) + T(N/2) + O(N) = 2T(N/2) + O(N)
A = 2,B=2,D=1

帶入master公式log(b,a) = 1,與d值相等翁狐。

于是歸并排序的時(shí)間復(fù)雜度為O(N * logN)类溢。

參考資料

【圖解數(shù)據(jù)結(jié)構(gòu)】 一組動(dòng)畫演示歸并排序
左神牛課網(wǎng)算法課
十大經(jīng)典排序算法(動(dòng)圖演示)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市露懒,隨后出現(xiàn)的幾起案子豌骏,更是在濱河造成了極大的恐慌龟梦,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,546評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件窃躲,死亡現(xiàn)場(chǎng)離奇詭異计贰,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)蒂窒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門躁倒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人洒琢,你說我怎么就攤上這事秧秉。” “怎么了衰抑?”我有些...
    開封第一講書人閱讀 164,911評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵象迎,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我呛踊,道長(zhǎng)砾淌,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,737評(píng)論 1 294
  • 正文 為了忘掉前任谭网,我火速辦了婚禮汪厨,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘愉择。我一直安慰自己劫乱,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評(píng)論 6 392
  • 文/花漫 我一把揭開白布锥涕。 她就那樣靜靜地躺著衷戈,像睡著了一般。 火紅的嫁衣襯著肌膚如雪层坠。 梳的紋絲不亂的頭發(fā)上脱惰,一...
    開封第一講書人閱讀 51,598評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音窿春,去河邊找鬼拉一。 笑死,一個(gè)胖子當(dāng)著我的面吹牛旧乞,可吹牛的內(nèi)容都是我干的蔚润。 我是一名探鬼主播,決...
    沈念sama閱讀 40,338評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼尺栖,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼嫡纠!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,249評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤除盏,失蹤者是張志新(化名)和其女友劉穎叉橱,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體者蠕,經(jīng)...
    沈念sama閱讀 45,696評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡窃祝,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了踱侣。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片粪小。...
    茶點(diǎn)故事閱讀 40,013評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖抡句,靈堂內(nèi)的尸體忽然破棺而出探膊,到底是詐尸還是另有隱情,我是刑警寧澤待榔,帶...
    沈念sama閱讀 35,731評(píng)論 5 346
  • 正文 年R本政府宣布逞壁,位于F島的核電站,受9級(jí)特大地震影響锐锣,放射性物質(zhì)發(fā)生泄漏腌闯。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評(píng)論 3 330
  • 文/蒙蒙 一刺下、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧稽荧,春花似錦橘茉、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至蟋恬,卻和暖如春翁潘,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背歼争。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工拜马, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人沐绒。 一個(gè)月前我還...
    沈念sama閱讀 48,203評(píng)論 3 370
  • 正文 我出身青樓俩莽,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親乔遮。 傳聞我的和親對(duì)象是個(gè)殘疾皇子扮超,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評(píng)論 2 355

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

  • 概述 排序有內(nèi)部排序和外部排序,內(nèi)部排序是數(shù)據(jù)記錄在內(nèi)存中進(jìn)行排序,而外部排序是因排序的數(shù)據(jù)很大出刷,一次不能容納全部...
    蟻前閱讀 5,186評(píng)論 0 52
  • 概述:排序有內(nèi)部排序和外部排序璧疗,內(nèi)部排序是數(shù)據(jù)記錄在內(nèi)存中進(jìn)行排序,而外部排序是因排序的數(shù)據(jù)很大馁龟,一次不能容納全部...
    每天刷兩次牙閱讀 3,732評(píng)論 0 15
  • 一些概念 數(shù)據(jù)結(jié)構(gòu)就是研究數(shù)據(jù)的邏輯結(jié)構(gòu)和物理結(jié)構(gòu)以及它們之間相互關(guān)系崩侠,并對(duì)這種結(jié)構(gòu)定義相應(yīng)的運(yùn)算,而且確保經(jīng)過這...
    Winterfell_Z閱讀 5,807評(píng)論 0 13
  • 如果要問這個(gè)世界有誰(shuí)不了解我屁柏,那大概就是我自己了啦膜。不管是公開的自我,秘密的自我淌喻,盲目的自我還是未知的自我僧家,我好像都...
    空洞美閱讀 303評(píng)論 0 2
  • 冬日的暖陽(yáng)斜斜的撒進(jìn)列車的窗戶,列車在行裸删,暖陽(yáng)在走八拱,心也在跟著流動(dòng),涯塔,肌稻, 9漂泊,是每個(gè)男兒的夢(mèng)匕荸,可以越高山爹谭,穿沙...
    唐古拉的雪閱讀 197評(píng)論 1 0