標籤:javascript演算法歸併排序 python演算法歸併排序 go演算法歸併排序 java演算法歸併排序
常見的內部排序演算法有:插入排序、希爾排序、選擇排序、冒泡排序、歸併排序、快速排序、堆排序、基數排序等。用一張圖概括:
650) this.width=650;" src="https://s4.51cto.com/wyfs02/M02/95/7B/wKioL1kVgaOibmjiAANCkj6aEBI037.png-wh_500x0-wm_3-wmp_4-s_2406916609.png" title="1513609480-59142359dda6f_articlex.png" alt="wKioL1kVgaOibmjiAANCkj6aEBI037.png-wh_50" />
歸併排序(英語:Merge sort,或mergesort),是建立在歸併操作上的一種有效排序演算法,效率為O(n log n)。1945年由約翰·馮·諾伊曼首次提出。該演算法是採用分治法(Divide and Conquer)的一個非常典型的應用,且各層分治遞迴可以同時進行。
650) this.width=650;" src="https://s2.51cto.com/wyfs02/M01/95/7B/wKioL1kVgdXQJ8-fAACgu50ZgtI663.png-wh_500x0-wm_3-wmp_4-s_1989658535.png" title="698676359-5915791dc7f34_articlex.png" alt="wKioL1kVgdXQJ8-fAACgu50ZgtI663.png-wh_50" />
作為一種典型的分而治之思想的演算法應用,歸併排序的實現由兩種方法:
自上而下的遞迴(所有遞迴的方法都可以用迭代重寫,所以就有了第 2 種方法);
自下而上的迭代;
在《資料結構與演算法 JavaScript 描述》中,作者給出了自下而上的迭代方法。但是對於遞迴法,作者卻認為:
However, it is not possible to do so in JavaScript, as the recursion goes too deep for the language to handle.
然而,在 JavaScript 中這種方式不太可行,因為這個演算法的遞迴深度對它來講太深了。
說實話,我不太理解這句話。意思是 JavaScript 編譯器記憶體太小,遞迴太深容易造成記憶體溢出嗎?還望有大神能夠指教。
和選擇排序一樣,歸併排序的效能不受輸入資料的影響,但表現比選擇排序好的多,因為始終都是 O(nlogn) 的時間複雜度。代價是需要額外的記憶體空間。
演算法步驟
申請空間,使其大小為兩個已經排序序列之和,該空間用來存放合并後的序列;
設定兩個指標,最初位置分別為兩個已經排序序列的起始位置;
比較兩個指標所指向的元素,選擇相對小的元素放入到合并空間,並移動指標到下一位置;
重複步驟 3 直到某一指標達到序列尾;
將另一序列剩下的所有元素直接複製到定序序列尾。
動圖示範
650) this.width=650;" src="https://s4.51cto.com/wyfs02/M00/95/7B/wKiom1kVgh2iycONAABQ8QHixJ4678.png-wh_500x0-wm_3-wmp_4-s_3543841057.png" title="440427741-591423a6c9b90_articlex.png" alt="wKiom1kVgh2iycONAABQ8QHixJ4678.png-wh_50" />
1、JavaScript 代碼實現
function mergeSort(arr) { var len = arr.length; if(len < 2) { return arr; } var middle = Math.floor(len / 2), left = arr.slice(0, middle), right = arr.slice(middle); return merge(mergeSort(left), mergeSort(right));}function merge(left, right){ var result = []; while (left.length && right.length) { if (left[0] <= right[0]) { result.push(left.shift()); } else { result.push(right.shift()); } } while (left.length) result.push(left.shift()); while (right.length) result.push(right.shift()); return result;}
2、Python 代碼實現
def mergeSort(arr): import math if(len(arr)<2): return arr middle = math.floor(len(arr)/2) left, right = arr[0:middle], arr[middle:] return merge(mergeSort(left), mergeSort(right))def merge(left,right): result = [] while left and right: if left[0] <= right[0]: result.append(left.pop(0)); else: result.append(right.pop(0)); while left: result.append(left.pop(0)); while right: result.append(right.pop(0)); return result
3、Go 代碼實現
func mergeSort(arr []int) []int { length := len(arr) if length < 2 { return arr } middle := length / 2 left := arr[0:middle] right := arr[middle:] return merge(mergeSort(left), mergeSort(right))}func merge(left []int, right []int) []int { var result []int for len(left) != 0 && len(right) != 0 { if left[0] <= right[0] { result = append(result, left[0]) left = left[1:] } else { result = append(result, right[0]) right = right[1:] } } for len(left) != 0 { result = append(result, left[0]) left = left[1:] } for len(right) != 0 { result = append(result, right[0]) right = right[1:] } return result}
4、Java 實現
public static int[] sort(int[] nums, int low, int high) { int mid = (low + high) / 2; if (low < high) { sort(nums, low, mid); sort(nums, mid + 1, high); merge(nums, low, mid, high); } return nums; } /** * 將數組中low到high位置的數進行排序 * nums 待排序數組 * low 待排的開始位置 * mid 待排中間位置 * high 待排結束位置 */ public static void merge(int[] nums, int low, int mid, int high) { int[] temp = new int[high - low + 1]; int i = low; int j = mid + 1; int k = 0; while (i <= mid && j <= high) { if (nums[i] < nums[j]) { temp[k++] = nums[i++]; } else { temp[k++] = nums[j++]; } } while (i <= mid) { temp[k++] = nums[i++]; } while (j <= high) { temp[k++] = nums[j++]; } for (int k2 = 0; k2 < temp.length; k2++) { nums[k2 + low] = temp[k2]; } }
希望可以一起交流技術,有興趣可以加qq邀請入群: 525331804 全棧技術開發qq群:581993430
本文出自 “知乎技術” 部落格,請務必保留此出處http://liuzhiying.blog.51cto.com/5850988/1925143
JavaScript演算法 ,Python演算法,Go演算法,java演算法,系列之【歸併排序】篇