常用排序算法:歸併排序與快速排序

一、歸併排序

歸併排序(MERGE-SORT)是利用歸併的思想實現的排序方法,該算法採用經典的分治(divide-and-conquer)策略(分治法將問題(divide)成一些小的問題然後遞歸求解,而治(conquer)的階段則將分的階段得到的各答案"修補"在一起,即分而治之)

可以看到這種結構很像一棵完全二叉樹,本文的歸併排序我們採用遞歸去實現(也可採用迭代的方式去實現)。階段可以理解爲就是遞歸拆分子序列的過程,遞歸深度爲log2n。

再來看看階段,我們需要將兩個已經有序的子序列合併成一個有序序列,比如上圖中的最後一次合併,要將[4,5,7,8]和[1,2,3,6]兩個已經有序的子序列,合併爲最終序列[1,2,3,4,5,6,7,8],來看下實現步驟。

從上文的圖中可看出,每次合併操作的平均時間複雜度爲O(n),而完全二叉樹的深度爲|log2n|。總的平均時間複雜度爲O(nlogn)。而且,歸併排序的最好,最壞,平均時間複雜度均爲O(nlogn)。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

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

            :: merged(xList, yTail)

      }

    }

    val = list.length / 2

    if (n == 0) list

    else {

      val (x, y) = list splitAt n

      merged(mergedSort(le)(x), mergedSort(le)(y))

    }

  }

二、快速排序

1.三步走:

(1) 選擇基準值。
(2) 將數組分成兩個子數組:小於基準值的元素和大於基準值的元素。
(3) 對這兩個子數組進行快速排序。

2.最簡單是以第一個元素爲基準

1

2

3

4

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))

  }

3.優化之三數取中法

就是取左端、中間、右端三個數,然後進行排序,將中間數作爲基準值。

 

根據基準值進行分割

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

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 = left

      //右指針

      var = right - 1

      while (i<j) {

        while (arr(i) < arr(pivot)) {

          i += 1}

        while (j > left && arr(j) > arr(pivot)) {

          = 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

  }