Chapter 26: O(n²) Sorting Algorithms

前言

O(n²)不算是效率很好的排序算法,但這類型算法是相對比較簡單好懂,這些算法在空間複雜度只需要O(1), 也相對優異。這些算法的基本原理都是comparison-based sorting method

大綱

  • Bubble sort

    • Example

    • Implementation

  • Selection sort

    • Example

    • Implementation

  • Insertion sort

    • Example

    • Implementation

  • Generalization

Bubble sort

  • Example

    • 每一回合,都是相鄰的兩邊一一進行比較,把較大的值仼右進行交換。

  • Implementation

public func bubbleSort<Element>(_ array: inout [Element]) where Element: Comparable {
    guard array.count > 2 else {
        return
    }

    // 第一個for loop是總共要比n-1回
    // end = [3, 2, 1]
    for end in (1..<array.count).reversed() {
        var swapped = false
        // 每一回要比end-1次
        // 每一回結束時,end位置已經是最大,所以下一回合,就只是需要比到end-1的位置就夠了
        for current in 0..<end {
            if array[current] > array[current + 1] {
                array.swapAt(current, current + 1)
                swapped = true
            }
        }
        // 如果有某個回合中,都沒有swap動作,就確保已經排序完成
        if !swapped {
            return
        }
    }
}

Selection sort

  • Example

    • 每一回合,都會找到最小的值,然後放到最左邊。

  • Implementation

public func selectionSort<Element>(_ array: inout [Element]) where Element: Comparable {
    guard array.count > 2 else {
        return
    }
    // 要比n-1回
    for current in 0..<(array.count - 1) {
        var lowest = current
        // 每一回結束時,current位置已經是最小,所以下一回合,就只是需要比到current+1的位置就夠了
        for other in (current + 1)..<array.count {
            if array[lowest] > array[other] {
                lowest = other
            }
        }
        // 比bubble優化的地方,只有在lowest不在current才進行swap
        if lowest != current {
            array.swapAt(lowest, current)
        }
    }
}

Insertion sort

  • Example

    • 每一回合,都是從從到右開始,每張卡回開始移動直到正確位置。

  • Implementation

public func insertionSort<Element>(_ array: inout [Element]) where Element: Comparable {
    guard array.count > 2 else {
        return
    }

    // 每一回合都要跟左邊開始比,index = 0沒有左邊,從index = 1開始比起
    // 要比n-2回
    for current in 1..<array.count {
        for shifting in (1...current).reversed() {
            // 每一回合依序跟左邊開始比
            if array[shifting] < array[shifting - 1] {
                array.swapAt(shifting, shifting - 1)
            } else {
                break
            }
        }

    }
}

Generalization

public func bubbleSort<T>(_ collection: inout T) where T: MutableCollection, T.Element: Comparable {
    guard collection.count >= 2 else {
        return
    }
    for end in collection.indices.reversed() {
        var swapped = false
        var current = collection.startIndex
        while current < end {
            let next = collection.index(after: current)
            if collection[current] > collection[next] {
                collection.swapAt(current, next)
                swapped = true
            }
            current = next
        }
        if !swapped {
            return
        }
    }
}

public func insertionSort<T>(_ collection: inout T)
    where T: BidirectionalCollection & MutableCollection,
    T.Element: Comparable {
        guard collection.count >= 2 else {
            return
        }
        for current in collection.indices {
            var shifting = current
            while shifting > collection.startIndex {
                let previous = collection.index(before: shifting)
                if collection[shifting] < collection[previous] {
                    collection.swapAt(shifting, previous)
                } else {
                    break
                }
                shifting = previous
            }
        }
}

public func selectionSort<T>(_ collection: inout T)
    where T: MutableCollection, T.Element: Comparable {
        guard collection.count >= 2 else {
            return
        }
        for current in collection.indices {
            var lowest = current
            var other = collection.index(after: current)
            while other < collection.endIndex {
                if collection[lowest] > collection[other] {
                    lowest = other
                }
                other = collection.index(after: other)
            }
            if lowest != current {
                collection.swapAt(lowest, current)
            }
        }
}

Last updated

Was this helpful?