Go歸并排序算法的實(shí)現(xiàn)方法
今天繼續(xù)基礎(chǔ)排序算法的圖解和Go 代碼實(shí)現(xiàn),這次分享一個(gè)時(shí)間復(fù)雜度為*** 誒,時(shí)間復(fù)雜度多少先保密,文末會(huì)有分析。這次分享的排序算法是—歸并排序(Merge Sort)。
歸并排序的思想
與快速排序一樣,歸并排序采用的也是分治的策略,把原本的問(wèn)題先分解成一些小問(wèn)題進(jìn)行求解,再把這些小問(wèn)題各自的答案修整到一起得到原本問(wèn)題的答案,從而達(dá)到分而治之的目的。
歸并排序算法會(huì)把要排序的序列分成長(zhǎng)度相當(dāng)?shù)膬蓚€(gè)子序列,當(dāng)分無(wú)可分每個(gè)子序列中只有一個(gè)數(shù)據(jù)的時(shí)候,就對(duì)子序列進(jìn)行歸并。
歸并指的是把兩個(gè)排序好的子序列合并成一個(gè)有序序列。該操作會(huì)一直重復(fù)執(zhí)行,直到所有子序列歸并為一個(gè)整體為止。
歸并排序的過(guò)程下面我們依然用圖例過(guò)一遍歸并排序?qū)σ粋€(gè)序列進(jìn)行排序的過(guò)程。
圖例出自—《我的第一本算法書(shū)》
首先,假設(shè)有下面這樣一個(gè)待排序的序列:
待排序的一串?dāng)?shù)字
將序列以對(duì)半分割的形式分成兩段。
把序列二分成兩段
再繼續(xù)對(duì)子序列進(jìn)行對(duì)半分割,分解下去。
再繼續(xù)往下分
直到分無(wú)可分,每個(gè)子序列中只有一個(gè)數(shù)據(jù)。
分解到每個(gè)子序列只有一個(gè)數(shù)據(jù)
接下來(lái)對(duì)分割后的數(shù)據(jù)進(jìn)行合并,合并時(shí)需要將數(shù)字按從小到大的順序排列。
合并序列時(shí)按大小排序
把 6 和 4 合并,合并時(shí)按照數(shù)字大小排序,合并后的順序?yàn)椤?,6】,接下來(lái)把 3 和 7 合并,合并后的順序?yàn)椤?,7】。
[繼續(xù)按照大小順序合并后面的序列]。
下面,我們看看怎么合并【4,6】和【3,7】這兩個(gè)序列。合并這種含有多個(gè)數(shù)字的子序列時(shí),要先比較首位數(shù)字,再移動(dòng)較小的數(shù)字。
合并多元素的序列時(shí),從首位開(kāi)始比較,小的先移動(dòng)
這里要比較兩個(gè)子序列的首位數(shù)字是4 和 3。由于 4 > 3,所以合并序列時(shí)先移動(dòng) 3。
4 > 3,所以合并序列時(shí)先移動(dòng) 3
接下來(lái),再按照比較兩個(gè)序列首位,小的先合并,大的留下來(lái)繼續(xù)比較的規(guī)則合并兩個(gè)序列。
4 小于 7,所以先移動(dòng) 4 到合并的序列。
由于4<7,所以移動(dòng)4
兩個(gè)子序列剩下的元素中,6 小于 7,所以先移動(dòng) 6。
6 < 7 所以先移動(dòng) 6
最后移動(dòng)剩下的 7。
子序列最后剩下了7,合并到序列中去
遞歸執(zhí)行上面的操作,直到所有的數(shù)字都合并到一個(gè)整體的序列上為止。
小序列合并成兩個(gè)大的序列
再繼續(xù)往完整的序列上合并
最后得到一個(gè)完整的排序完成的序列 。
排序完成的序列
歸并排序的 Go 代碼實(shí)現(xiàn)
下面上一個(gè)用歸并排序的Go代碼實(shí)現(xiàn),代碼很簡(jiǎn)單,實(shí)現(xiàn)步驟就都放在了代碼的注釋里,就不再多說(shuō)啦,先收藏文章(也要記得點(diǎn)贊),等有時(shí)間了自己在電腦上運(yùn)行一下試試吧。
package main import "fmt" // 自頂向下歸并排序,排序范圍在 [begin,end) 的數(shù)組 func MergeSort(array []int, begin int, end int) { // 元素?cái)?shù)量大于1時(shí)才進(jìn)入遞歸 if end - begin > 1 { // 將數(shù)組一分為二,分為 array[begin,mid) 和 array[mid,high) mid := begin + (end-begin+1)/2 // 先將左邊排序好 MergeSort(array, begin, mid) // 再將右邊排序好 MergeSort(array, mid, end) // 兩個(gè)有序數(shù)組進(jìn)行合并 merge(array, begin, mid, end) } } // 歸并操作 func merge(array []int, begin int, mid int, end int) { // 申請(qǐng)額外的空間來(lái)合并兩個(gè)有序數(shù)組,這兩個(gè)數(shù)組是 array[begin,mid),array[mid,end) leftSize := mid - begin // 左邊數(shù)組的長(zhǎng)度 rightSize := end - mid // 右邊數(shù)組的長(zhǎng)度 newSize := leftSize + rightSize // 輔助數(shù)組的長(zhǎng)度 result := make([]int, 0, newSize) l, r := 0, 0 for l < leftSize && r < rightSize { lValue := array[begin+l] // 左邊數(shù)組的元素 rValue := array[mid+r] // 右邊數(shù)組的元素 // 小的元素先放進(jìn)輔助數(shù)組里 if lValue < rValue { result = append(result, lValue) l++ } else { result = append(result, rValue) r++ } // 將剩下的元素追加到輔助數(shù)組后面 result = append(result, array[begin+l:mid]...) result = append(result, array[mid+r:end]...) // 將輔助數(shù)組的元素復(fù)制回原數(shù)組,這樣該輔助空間就可以被釋放掉 for i := 0; i < newSize; i++ { array[begin+i] = result[i] return
歸并排序的時(shí)間復(fù)雜度
老規(guī)矩,看完算法思想和實(shí)現(xiàn)步驟后,我們?cè)賮?lái)分析一下歸并排序算法的時(shí)間復(fù)雜度。
歸并排序中,分割序列所花費(fèi)的時(shí)間不算在運(yùn)行時(shí)間內(nèi) (可以當(dāng)作序列本來(lái)就是分 割好的)。在合并兩個(gè)已排好序的子序列時(shí),只需依次比較處在序列首位數(shù)據(jù)的大小,然后移動(dòng)較小的數(shù)據(jù),因此只需花費(fèi)和兩個(gè)子序列的長(zhǎng)度相應(yīng)的運(yùn)行時(shí)間。也就是說(shuō),完成一行歸并所需的運(yùn)行時(shí)間取決于這一行的數(shù)據(jù)量。
看一下這個(gè)圖便能得知,無(wú)論哪一行都是 n 個(gè)數(shù)據(jù),所以每行的運(yùn)行時(shí)間都為 O(n)。
歸并排序每一行的數(shù)據(jù)都是 n 個(gè)
而將長(zhǎng)度為 n 的序列對(duì)半分割直到只有一個(gè)數(shù)據(jù)為止時(shí),可以分成 行,因此,總共有 log2n 行。也就是說(shuō),總的運(yùn)行時(shí)間為 ,這與前面講到的快速排序相同。
到此這篇關(guān)于Go歸并排序算法的實(shí)現(xiàn)方法的文章就介紹到這了,更多相關(guān)go歸并排序算法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
利用Go語(yǔ)言搭建WebSocket服務(wù)端方法示例
這篇文章主要給大家介紹了利用Go語(yǔ)言搭建WebSocket服務(wù)端方法,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友們可以參考借鑒,下面來(lái)一起看看吧。2017-04-04golang使用go mod導(dǎo)入本地包和第三方包的方式
這篇文章主要介紹了golang使用go mod導(dǎo)入本地包和第三方包的方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01Golang干貨分享之利用AST實(shí)現(xiàn)AOP功能
本文主要是一個(gè)純干貨分享,主要介紹了Golang如何利用AST實(shí)現(xiàn)AOP功能,文中的示例代碼簡(jiǎn)潔易懂,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-04-04Go語(yǔ)言用map實(shí)現(xiàn)堆棧功能的方法
這篇文章主要介紹了Go語(yǔ)言用map實(shí)現(xiàn)堆棧功能的方法,實(shí)例分析了Go語(yǔ)言使用map操作堆棧的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-02-02Golang多線程排序?qū)崿F(xiàn)快速高效地處理大規(guī)模數(shù)據(jù)
Golang多線程排序是一種快速高效地處理大規(guī)模數(shù)據(jù)的方法,通過(guò)使用Golang的協(xié)程和通道,可以將排序任務(wù)分配到多個(gè)線程中并行處理,提高了排序的效率和速度,需要詳細(xì)了解可以參考下文2023-05-05golang如何通過(guò)type定義函數(shù)類(lèi)型
這篇文章主要介紹了golang如何通過(guò)type定義函數(shù)類(lèi)型問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01Golang Map value不可尋址使用指針類(lèi)型代替示例詳解
這篇文章主要為大家介紹了Golang Map value不可尋址使用指針類(lèi)型代替示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11windows下使用vscode搭建golang環(huán)境并調(diào)試的過(guò)程
這篇文章主要介紹了在windows下使用vscode搭建golang環(huán)境并進(jìn)行調(diào)試,主要包括安裝方法及環(huán)境變量配置技巧,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-09-09Golang 模塊引入及表格讀寫(xiě)業(yè)務(wù)快速實(shí)現(xiàn)示例
這篇文章主要為大家介紹了Golang模塊引入及表格讀寫(xiě)業(yè)務(wù)的快速實(shí)現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07