程序員:算法導(dǎo)論掂骏,分治法轰驳、歸并排序,偽代碼和Java實(shí)現(xiàn)

分治法

我們首先先介紹分治法。分治法的思想:將原問(wèn)題分解為幾個(gè)規(guī)模較小但類(lèi)似于原問(wèn)題的子問(wèn)題级解,遞歸地求解這些子問(wèn)題冒黑,然后在合并這些子問(wèn)題的解來(lái)解決原問(wèn)題的解。

還是拿撲克牌舉例子勤哗,假設(shè)桌上有兩堆牌面朝上的牌(牌面朝上:有值)抡爹,每堆都已排序,最小的牌在頂上芒划。我們希望把這兩堆牌合并成單一的排好序的輸出堆冬竟,牌面朝下地放在桌上。應(yīng)該怎么做呢民逼?

我們的做法是:在牌面朝上的兩堆牌的頂上兩張牌中選取較小的一張泵殴,將該牌從其堆中移開(kāi)(該堆的頂上將顯示一張新牌)并牌面朝下地將該牌放置到輸出堆。重復(fù)這個(gè)步驟直到兩堆牌都沒(méi)有牌拼苍。

下面我們來(lái)實(shí)現(xiàn)上面所提的思想

為了避免在某個(gè)基本步驟必須檢查是否有堆為空袋狞。在每個(gè)堆的底部放置一張哨兵牌,它包含一個(gè)特殊的值(很大的值映屋,使它不可能是較小的牌苟鸯,除非兩個(gè)堆都已顯露出其哨兵牌。一旦發(fā)生這種情況棚点,說(shuō)明非哨兵牌都已被放置到輸出堆)早处,用于簡(jiǎn)化代碼。

偽代碼:

MERGE(A,p,q,r)n1 = q - p + 1n2 = r - q//L[1..n1+1] and R[1..n2+1]是新的數(shù)組for i = 1 to n1L[i] = A[p + i -1]for j = 1 to n2R[j] = A[q + j]L[n1 + 1] = ∞R[n2 + 1] = ∞i = 1j = 1for k = p to rif L[i] <= R[j]A[k] = L[i]i = i + 1elseA[k] = R[j]j = j + 1

Java實(shí)現(xiàn):

public void Merge(int[] A,int p,int q,int r){int n1 = q - p + 1;int n2 = r - q;//L[1..n1+1] and R[1..n2+1]是新的數(shù)組int[] L = new int[n1 + 1];int[] R = new int[n2 + 1];for (int i = 0;i < n1;i++){L[i] = A[p + i];}for (int j = 0;j < n2;j++){R[j] = A[q + j + 1];}L[n1] = Integer.MAX_VALUE;R[n2] = Integer.MAX_VALUE;int i = 0,j = 0;for (int k = p;k <= r;k++){if (L[i] <= R[j]){A[k] = L[i];i = i + 1;}else{A[k] = R[j];j = j + 1;}}}下面我們來(lái)看一下分治法的步驟

對(duì)數(shù)組A[2,4,7,1,3,6]調(diào)用Merge(A,0,2,5)

初始狀態(tài)

初始完L和R數(shù)組之后瘫析,現(xiàn)在進(jìn)入for循環(huán)階段砌梆。讓L中i所指的值和R數(shù)組中j所指的值進(jìn)行比較,把較小的值放入數(shù)組A中k所指的位置贬循。并且讓較小的值的索引i或j前進(jìn)一格(+1)咸包。因?yàn)長(zhǎng)和R數(shù)組已經(jīng)從小到大排好序了,所以找出來(lái)的最小值一定是當(dāng)前L和R數(shù)組的最小值杖虾,放入了數(shù)組A中也是排好序的烂瘫,所以讓k前進(jìn)一步,k=k+1,然后執(zhí)行下一次循環(huán)奇适。

第一此循環(huán):i和j初始為0坟比,k=p=0,讓L[0]與R[0]進(jìn)行比較 L[0]>R[0]所以R[0]是較小值嚷往,把A[0]替換為R[0]葛账。讓j=j+1,i保持不變皮仁。k=k+1=1籍琳,開(kāi)啟下一次循環(huán)菲宴。本次循環(huán)結(jié)果如下圖所示:

A中的灰色位置包含將被覆蓋的值,L和R中的灰色位置包含有待于被復(fù)制回A的值趋急,A中的黃色位置包含它們的最終值喝峦,L和R中的黃色位置包含已被復(fù)制回A的值。

第二次循環(huán):此時(shí)i=0宣谈,j=1愈犹,k=1键科,讓L[i]和R[j]進(jìn)行比較闻丑,L[0]<R[1],所以L(fǎng)[0]是較小值勋颖,把A[k]即A[1]替換為L(zhǎng)[0]嗦嗡。讓i=i+1,j保存不變饭玲。k=k+1=2侥祭,開(kāi)啟下一次循環(huán)。本次循環(huán)結(jié)果如下圖所示:

第三次循環(huán):此時(shí)i=1茄厘,j=1矮冬,k=2,讓L[i]和R[j]進(jìn)行比較次哈,L[1]>R[1]胎署,所以R[1]是較小值,把A[2]即A[2]替換為R[1]窑滞。讓j=j+1琼牧,i保存不變。k=k+1=3哀卫,開(kāi)啟下一次循環(huán)巨坊。本次循環(huán)結(jié)果如下圖所示:

第四次循環(huán):此時(shí)i=1,j=2此改,k=3趾撵,讓L[i]和R[j]進(jìn)行比較,L[1]<R[2]共啃,所以L(fǎng)[1]是較小值鼓寺,把A[k]即A[3]替換為L(zhǎng)[1]。讓i=i+1勋磕,j保存不變妈候。k=k+1=4,開(kāi)啟下一次循環(huán)挂滓。本次循環(huán)結(jié)果如下圖所示:

第五次循環(huán):此時(shí)i=2苦银,j=2,k=4,讓L[i]和R[j]進(jìn)行比較幔虏,L[2]>R[2]纺念,所以R[2]是較小值,把A[k]即A[4]替換為R[2]想括。讓j=j+1陷谱,j保存不變。k=k+1=4瑟蜈,開(kāi)啟下一次循環(huán)烟逊。本次循環(huán)結(jié)果如下圖所示:

注意:此時(shí)j已經(jīng)到達(dá)了R數(shù)組的最后一個(gè)數(shù)∞,L數(shù)組中的每個(gè)數(shù)都比∞小铺根,即不等式L[i]>R[j]恒成立宪躯。所以不管L剩下多少個(gè)數(shù),都會(huì)按照順序放置A中位迂,直到i也達(dá)到了最后一個(gè)數(shù)∞访雪,此時(shí)k>r,循環(huán)已經(jīng)全部結(jié)束掂林。

第六次循環(huán):此時(shí)i=2臣缀,j=3,k=5泻帮,讓L[i]和R[j]進(jìn)行比較精置,L[2]<R[3],所以L(fǎng)[2]是較小值刑顺,把A[k]即A[5]替換為L(zhǎng)[2]氯窍。讓i=i+1,j保存不變蹲堂。k=k+1=6狼讨,開(kāi)啟下一次循環(huán)。本次循環(huán)結(jié)果如下圖所示:

第七次循環(huán)柒竞,此時(shí)i=2政供,j=3,k=6朽基,我們的r=5布隔,判斷條件k<=r為false,循環(huán)結(jié)束稼虎。

分治法的應(yīng)用——?dú)w并排序

上面講到了分治法衅檀,分治法有個(gè)很大的限制就是L和R是排好序的才可以。但是許多數(shù)組都是很亂的順序霎俩。那么怎么解決這個(gè)問(wèn)題呢哀军?試想一下如果L和R數(shù)組的大小為1沉眶,那么L和R數(shù)組肯定是排好序的。對(duì)的杉适!我們可以把一個(gè)大的數(shù)組遞歸拆分成小的子數(shù)組谎倔,子數(shù)組在遞歸拆分成更小的子數(shù)組。直到遞歸到的L和R數(shù)組的大小為1時(shí)猿推,調(diào)用MERGE分治法片习。隨著算法自底向上地推進(jìn):合并只含1項(xiàng)的序列對(duì)形成長(zhǎng)度為2的排好序的序列,合并長(zhǎng)度為2的序列對(duì)形成長(zhǎng)度為4的排好序的序列蹬叭,依次下去藕咏,直到長(zhǎng)度為n/2的兩個(gè)序列被合并最終形成長(zhǎng)度為n的排好序的序列,數(shù)組最終會(huì)排序完成具垫。

如下圖所示

我們可以把上面提到的MERGE作為歸并排序算法中的一個(gè)子程序來(lái)用侈离。

下面的過(guò)程MERGE-SORT(A,p,r)排序子數(shù)組A[p…r]中的元素试幽。若p>=r,則該子數(shù)組最多有一個(gè)元素筝蚕,所以已經(jīng)排好序。否則铺坞,分解步驟簡(jiǎn)單地計(jì)算一個(gè)下標(biāo)q起宽,將A[p…r]分成兩個(gè)子數(shù)組A[p…q]和A[q+1…r],前者包含n/2個(gè)元素济榨,后者包含n/2個(gè)元素坯沪。

偽代碼:

MERGE-SORT(A,p,r)if p < rq = (p+r)/2MERGE-SORT(A,p,q)MERGE-SORT(A,q+1,r)MERGE(A,p,q,r)

java實(shí)現(xiàn):

public void MergeSort(int[] A,int p,int r) {if (p < r){int q =(int)Math.floor((p+r)/2);MergeSort(A,p,q); //將左半邊排序MergeSort(A,q+1,r); //將右半邊排序Merge(A,p,q,r); //歸并結(jié)果}}

下面我們來(lái)看一下歸并排序在數(shù)組A=[5,2,4,7,1,3,2,6]上的操作,隨著算法自底向上地推進(jìn)擒滑,待合并的已排好序的各序列的長(zhǎng)度不斷增加腐晾。


合肥北大青鳥(niǎo)一元校區(qū)是隸屬于北大青鳥(niǎo)旗下的一家IT培訓(xùn)機(jī)構(gòu),這里有豐富的Java教育資源丐一,完善的教育體系藻糖,和多個(gè)大型企業(yè)擁有合作,學(xué)員學(xué)完課程之后推薦就業(yè)【北大青鳥(niǎo)一元校區(qū) www.kgcbdqn.com】百度搜索“北大青鳥(niǎo)一元校區(qū)”,即可領(lǐng)取試聽(tīng)課程

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末库车,一起剝皮案震驚了整個(gè)濱河市巨柒,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌柠衍,老刑警劉巖洋满,帶你破解...
    沈念sama閱讀 219,539評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異珍坊,居然都是意外死亡牺勾,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門(mén)阵漏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)驻民,“玉大人腺怯,你說(shuō)我怎么就攤上這事〈ㄎ蓿” “怎么了呛占?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,871評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)懦趋。 經(jīng)常有香客問(wèn)我晾虑,道長(zhǎng),這世上最難降的妖魔是什么仅叫? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,963評(píng)論 1 295
  • 正文 為了忘掉前任帜篇,我火速辦了婚禮,結(jié)果婚禮上诫咱,老公的妹妹穿的比我還像新娘笙隙。我一直安慰自己,他們只是感情好坎缭,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評(píng)論 6 393
  • 文/花漫 我一把揭開(kāi)白布竟痰。 她就那樣靜靜地躺著,像睡著了一般掏呼。 火紅的嫁衣襯著肌膚如雪坏快。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,763評(píng)論 1 307
  • 那天憎夷,我揣著相機(jī)與錄音莽鸿,去河邊找鬼。 笑死拾给,一個(gè)胖子當(dāng)著我的面吹牛祥得,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蒋得,決...
    沈念sama閱讀 40,468評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼级及,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了窄锅?” 一聲冷哼從身側(cè)響起创千,我...
    開(kāi)封第一講書(shū)人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎入偷,沒(méi)想到半個(gè)月后追驴,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,850評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡疏之,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評(píng)論 3 338
  • 正文 我和宋清朗相戀三年殿雪,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片锋爪。...
    茶點(diǎn)故事閱讀 40,144評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡丙曙,死狀恐怖爸业,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情亏镰,我是刑警寧澤扯旷,帶...
    沈念sama閱讀 35,823評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站索抓,受9級(jí)特大地震影響钧忽,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜逼肯,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評(píng)論 3 331
  • 文/蒙蒙 一耸黑、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧篮幢,春花似錦大刊、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,026評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至赋续,卻和暖如春男翰,著一層夾襖步出監(jiān)牢的瞬間另患,已是汗流浹背纽乱。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,150評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留昆箕,地道東北人鸦列。 一個(gè)月前我還...
    沈念sama閱讀 48,415評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像鹏倘,于是被迫代替她去往敵國(guó)和親薯嗤。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評(píng)論 2 355

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