美文网首页
归并排序(Merge Sort)

归并排序(Merge Sort)

作者: Bel李玉 | 来源:发表于2020-07-19 23:34 被阅读0次

归并排序是最高效的排序算法之一。该排序算法的时间复杂度是O(log n),归并排序是由分割和合并组成的。将一个比较大的问题分割成若干容易解决的小问题,然后进行合并,得到一个最终的结果。归并排序的口诀就是先分割,后合并。

举个例子,假定你手中有如下一摞卡牌:


mergeSort1.png

排序算法的排序过程大致是这样的:
1,首先,将这一摞牌分成两半,这样就得到了两摞无序的卡牌。


mergeSort2.png
1,现在继续对每摞卡牌进行分割,直到不能在分割为止,到最后在每摞卡牌中,就只存在一张卡牌。
mergeSort3.png

1,最后,以和分割相反的顺序,将每一摞卡牌合并。在每一次合并的过程中,将数据按照规则进行排序。由于每一小摞的卡牌都已经有序,在合并的时候会比较容易些。


mergeSort4.png

实现

分割

首先,先将数组分成两半:

public func mergeSort<Element>(_ array: [Element])
    -> [Element] where Element: Comparable {
  let middle = array.count / 2
  let left = Array(array[..<middle])
  let right = Array(array[middle...])
  // ... more to come
}

将数组分割一次远远不够,需要递归调用分割函数,直到不能在分割为止。这样的话,每一个子部分都只包含一个元素。按照这种思路,我们将 mergeSort 更新至如下所示:

public func mergeSort<Element>(_ array: [Element])
    -> [Element] where Element: Comparable {
  // 1
  guard array.count > 1 else {
    return array
  }
  let middle = array.count / 2
  // 2
  let left = mergeSort(Array(array[..<middle]))
  let right = mergeSort(Array(array[middle...]))
  // ... more to come
}

这里有两个变动点:
1,对函数进行了递归调用,在数组中有且只有一个元素时,停止递归调用。
2,对原数组的左右子数组都调用 mergeSort

如上代码在能通过编译之前,仍然还有很多事情去做。现在已经完成了数组分割部分,是时候去关注于合并了。

合并

合并左右子数组是该算法的最后一步。为了更算法更明了一些,单独创建一个 merge 方法。

merge 方法的职责仅仅是 将两个将两个有序的数组合并成一个有序的数组。在 mergeSort 函数中,增加以下方法:

private func merge<Element>(_ left: [Element], _ right: [Element])
    -> [Element] where Element: Comparable {
  // 1
  var leftIndex = 0
  var rightIndex = 0
  // 2
  var result: [Element] = []
  // 3
  while leftIndex < left.count && rightIndex < right.count {
    let leftElement = left[leftIndex]
    let rightElement = right[rightIndex]
    // 4
    if leftElement < rightElement {
      result.append(leftElement)
      leftIndex += 1
    } else if leftElement > rightElement {
      result.append(rightElement)
      rightIndex += 1
    } else {
      result.append(leftElement)
      leftIndex += 1
      result.append(rightElement)
      rightIndex += 1
    }
  }
  // 5
  if leftIndex < left.count {
    result.append(contentsOf: left[leftIndex...])
  }
  if rightIndex < right.count {
    result.append(contentsOf: right[rightIndex...])
  }
  return result
}
  • 1,leftIndexrightIndex 变量记录着遍历两个数组的进度。

  • 2,resultArray 是最终排过序的数组。

  • 3,从开头依次比较左右数组的元素,如果已经到达任意一个数组的末端,就没有元素去比较了。

  • 4,比较两个元素,将比较小的元素放入resultArray,如果两个元素相等,把他俩都加入到数组中。

  • 5,第一个循环保证了左数组或者右数组有一个已经添加完,由于数组都是有序的,这就保证了,数组中遗留的元素都是大于等于 result 里面的元素。

最后附上本文的相关代码DataAndAlgorim

参考链接《Data Structures & Algorithms in Swift》

相关文章

  • 排序算法-5--- 归并排序

    归并排序 Merge sort 1、概念 归并排序(英语:Merge sort,或mergesort),是创建在归...

  • 归并排序和快速排序

    1.归并排序(Merge Sort) 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算...

  • JavaScript的排序算法——归并排序

    归并排序(Merge Sort) 在计算机科学里,归并排序(Merge Sort)是一种通用有效的排序算法。通常情...

  • c算法O(n*log n)(二)

    归并排序Merge Sort 自顶向下进行排序 自底向上进行归并排序 快速排序

  • 归并排序

    来源:图解排序算法(四)之归并排序 - dreamcatcher-cx - 博客园 归并排序(MERGE-SORT...

  • 排序算法(2):归并排序

     归并排序:归并排序(英语:Merge sort,或mergesort),是创建在归并操作上的一种有效的排序算法,...

  • python归并排序--递归实现

    归并排序: 归并排序(英语:Merge sort,或mergesort),是创建在归并操作上的一种有效的排序算法,...

  • 排序算法之归并排序

    归并排序(Merge Sort) 归并排序是利用归并的思想实现排序的方式,该算法采用的是经典的分治算法 归并排序过...

  • 归并排序

    什么是归并排序? 归并排序(Merge sort,或mergesort),是创建在归并操作上的一种有效的排序算法,...

  • 05_归并排序

    def merge_sort(data): ''' 归并排序 :param lists: :ret...

网友评论

      本文标题:归并排序(Merge Sort)

      本文链接:https://www.haomeiwen.com/subject/cowrkktx.html