Chapter 28: Merge Sort
前言
Merge sort主要利用的是divide-and-conquer來進行排序,跟前面學到comparison-based(Bubble, Selection, Inserction)是完全不同的概念。
大綱
Implementation
Split
Merge
Finishing up
Performance
Split
不斷遞迴分割整個資料集,直到整個資料集達到base case, 以這個例子而言,當切割每個資料集的元素個數為1,表示已切割完成。
public func mergeSort<Element>(_ array: [Element]) -> [Element] where Element: Comparable {
// 達到base case不在遞迴下去
guard array.count > 2 else {
return array
}
// 先進行split動作
let middle = array.count / 2
let left = mergeSort(Array(array[0..<middle]))
let right = mergeSort(Array(array[middle...]))
}
Merge
將left和right從小範圍的資料集不斷合併成大的
private func merge<Element>(_ left: [Element], _ right: [Element]) -> [Element] where Element: Comparable {
var leftIndex = 0
var rightIndex = 0
var result: [Element] = []
// 這個loop結束後,一定是左邊或右邊的所有元素已經都加入result
while leftIndex < left.count && rightIndex < right.count {
let leftElement = left[leftIndex]
let rightElement = right[rightIndex]
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
}
}
// 如果是左邊有剩
if leftIndex < left.count {
result.append(contentsOf: left[leftIndex...])
}
// 如果是右邊有剩
if rightIndex < right.count {
result.append(contentsOf: right[rightIndex...])
}
return result
}
Finishing up
The strategy of merge sort is to divide and conquer, so that you solve many small problems instead of one big problem.
It has two core responsibilities: a method to divide the initial array recursively, as well as a method to merge two arrays.
The merging function should take two sorted arrays and produce a single sorted array.
public func mergeSort<Element>(_ array: [Element])
-> [Element] where Element: Comparable {
guard array.count > 1 else {
return array
}
let middle = array.count / 2
let left = mergeSort(Array(array[..< middle]))
let right = mergeSort(Array(array[middle...]))
return merge(left, right)
}
Performance
切割: 是利用遞迴方式切割
In general, if you have an array of size n, the number of levels is log2(n).
合併: 每次合併都是將n個元素(可能被切成很n堆)進行左右合併
A single recursion level will merge n elements. This means the cost of a single recursion is O(n)
This brings the total cost to O(log n) × O(n) = O(n log n).
雖然Merge sort的速度比之前講的0(n^2)還要快,但代價就是犧牲空間複雜度
There are log2(n) levels of recursion and at each level n elements are used. That makes the total O(n log n) in space complexity
Last updated
Was this helpful?