# mergeSort ###### tags: `排序` `mergesort` 合併排序法(Merge Sort)原理是會先將原始資料分割成兩個資料列,接著再將兩個資料繼續分割成兩個資料列,依此類推,直到無法再分割,也就是每組都只剩下一筆資料時,再兩兩合併各組資料,合併時也會進行該組排序,每次排序都是比較最左邊的資料,將較小的資料加到新的資料列中,依此類推,直到最後合併成一個排序好的資料列為止。 下面利用 ``` 30 10 40 70 50 90 60 20 ``` 由小到大排序。 ![Uploading file..._syzt76yk9]() `時間複雜度 = 分割步驟數 + 合併步驟數` 分割:分割含有 n 個資料需要 n-1 次,O(n)。合併:合併的兩邊共用 n 個元素,每次都是比較最左邊的資料,將較小的加到新陣列中,因此每次排序與合併必須經過 n 次,每回合log n次,O(log n)。 每回合意思是指每一行算一回合,因為每次都是2 的指數在成長,所以只需要logn ,但是合併同時需要sort 就需要n次 ,所以平均複雜度是nlogn # 分割的部分程式碼(幫助理解用) 遞迴就是 第一層我們原本要return 但是發現devide(right )是一個未知的東西,於是我們就想要得到一個確定的值,所以我們就執行他,去求解,然後一直這樣持續,直到最後一層,return data 終於有個確定的值了,就依造順序,往上給原本執行他要求解的層,然後又一值這樣持續,直到最上層,把我們一開始想要return 的確定的值找到了,就return 給主函式data ,並結束遞迴 ```python= data = [89, 34, 23, 78, 67, 100, 66, 29, 79, 55, 78, 88, 92, 96, 96, 23] def devide(data): if len(data)<2: return data n=len(data) mid=n//2 right=data[mid:] left=data[:mid] print("目前的總長度=",n,"//////","目前的中點位置",mid) print(left,"-----",right) return devide(left), devide(right) devide(data) ``` 輸出 ```python= 目前的長度= 16 ////// 目前的中點位置 8 [89, 34, 23, 78, 67, 100, 66, 29] ----- [79, 55, 78, 88, 92, 96, 96, 23] 目前的長度= 8 ////// 目前的中點位置 4 [89, 34, 23, 78] ----- [67, 100, 66, 29] 目前的長度= 4 ////// 目前的中點位置 2 [89, 34] ----- [23, 78] 目前的長度= 2 ////// 目前的中點位置 1 [89] ----- [34] 目前的長度= 2 ////// 目前的中點位置 1 [23] ----- [78] 目前的長度= 4 ////// 目前的中點位置 2 [67, 100] ----- [66, 29] 目前的長度= 2 ////// 目前的中點位置 1 [67] ----- [100] 目前的長度= 2 ////// 目前的中點位置 1 [66] ----- [29] 我們可以看到他都是先分右邊,分到底之後才去拿左邊來分,這和最後我們return 的順序有關 目前的長度= 8 ////// 目前的中點位置 4 [79, 55, 78, 88] ----- [92, 96, 96, 23] 目前的長度= 4 ////// 目前的中點位置 2 [79, 55] ----- [78, 88] 目前的長度= 2 ////// 目前的中點位置 1 [79] ----- [55] 目前的長度= 2 ////// 目前的中點位置 1 [78] ----- [88] 目前的長度= 4 ////// 目前的中點位置 2 [92, 96] ----- [96, 23] 目前的長度= 2 ////// 目前的中點位置 1 [92] ----- [96] 目前的長度= 2 ////// 目前的中點位置 1 [96] ----- [23] ``` 全部程式碼 ```python= data = [89, 34, 23, 78, 67, 100, 66, 29, 79, 55, 78, 88, 92, 96, 96, 23] def devide(data): if len(data)<2: return data n=len(data) mid=n//2 right=data[mid:] left=data[:mid] print("目前的總長度=",n,"//////","目前的中點位置",mid) print(left,"-----",right) return merge(devide(left), devide(right)) # 這邊因為平行一起傳入一個function 所以為logN def merge(right,left): result=[] while len(right) and len(left): if right[0]>left[0]: result.append(left.pop(0))#這邊用pop我們就不用在移動index 直接取出就好 else : result.append(right.pop(0)) result= result+right if len(right) else result+left return result print(devide(data)) ```