歸併排序(MERGE-SORT)是利用歸併的思想實現的排序方法,該算法採用經典的分治(divide-and-conquer)策略(分治法將問題分(divide)成一些小的問題而後遞歸求解,而治(conquer)的階段則將分的階段獲得的各答案"修補"在一塊兒,即分而治之)算法
能夠看到這種結構很像一棵徹底二叉樹,本文的歸併排序咱們採用遞歸去實現(也可採用迭代的方式去實現)。分階段能夠理解爲就是遞歸拆分子序列的過程,遞歸深度爲log2n。數組
再來看看治階段,咱們須要將兩個已經有序的子序列合併成一個有序序列,好比上圖中的最後一次合併,要將[4,5,7,8]和[1,2,3,6]兩個已經有序的子序列,合併爲最終序列[1,2,3,4,5,6,7,8],來看下實現步驟。ide
從上文的圖中可看出,每次合併操做的平均時間複雜度爲O(n),而徹底二叉樹的深度爲|log2n|。總的平均時間複雜度爲O(nlogn)。並且,歸併排序的最好,最壞,平均時間複雜度均爲O(nlogn)。優化
def mergedSort[T](le: (T, T) => Boolean)(list: List[T]): List[T] = { def merged(xList: List[T], yList: List[T]): List[T] = { (xList, yList) match { case (Nil, _) => yList case (_, Nil) => xList case (x :: xTail, y :: yTail) => if (le(x, y)) x :: merged(xTail, yList) else y :: merged(xList, yTail) } } val n = list.length / 2 if (n == 0) list else { val (x, y) = list splitAt n merged(mergedSort(le)(x), mergedSort(le)(y)) } }
(1) 選擇基準值。
(2) 將數組分紅兩個子數組:小於基準值的元素和大於基準值的元素。
(3) 對這兩個子數組進行快速排序。ui
def qsort[T](list: List[T])(implicit t:T=>Ordered[T]):List[T]=list match { case Nil=>Nil case ::(pivot,tail) => qsort(tail.filter(_<=pivot)) ++ List(pivot) ++ qsort(tail.filter(_>pivot)) }
就是取左端、中間、右端三個數,而後進行排序,將中間數做爲基準值。scala
根據基準值進行分割3d
def quickSort(arr: Array[Int]): Unit = quickSort(arr,0,arr.length-1) def quickSort(arr: Array[Int], left: Int, right: Int): Unit ={ if (left < right) { dealPivot(arr, left, right) //基準值放在倒數第二位 val pivot = right - 1 //左指針 var i = left //右指針 var j = right - 1 while (i<j) { while (arr(i) < arr(pivot)) { i += 1} while (j > left && arr(j) > arr(pivot)) { j = j - 1} swap(arr, i, j) } if (i < right) swap(arr, i, right - 1) quickSort(arr, left, i - 1) quickSort(arr, i + 1, right) } } // 處理基準值 def dealPivot(arr: Array[Int], left: Int, right: Int): Unit = { val mid = (left + right) / 2 if (arr(left) > arr(mid)) swap(arr, left, mid) if (arr(left) > arr(right)) swap(arr, left, right) if (arr(right) < arr(mid)) swap(arr, right, mid) swap(arr, right - 1, mid) } // 交換元素通用處理 private def swap(arr: Array[Int], a: Int, b: Int) = { val temp = arr(a) arr(a) = arr(b) arr(b) = temp }