Docs
Documentation Fundamentals

Searching & Sorting

Overview

Searching and sorting are fundamental operations in computer science and software development. Swift provides built-in methods, but understanding and implementing common algorithms from scratch is essential for building a strong foundation in data structures and algorithms.

Searching Algorithms

  • Time Complexity: O(n)

  • Use when data is unsorted

func linearSearch<T: Equatable>(_ array: [T], target: T) -> Int? {
    for (index, value) in array.enumerated() {
        if value == target {
            return index
        }
    }
    return nil
}
  • Time Complexity: O(log n)

  • Requires sorted array

func binarySearch<T: Comparable>(_ array: [T], target: T) -> Int? {
    var low = 0
    var high = array.count - 1

    while low <= high {
        let mid = low + (high - low) / 2
        if array[mid] == target {
            return mid
        } else if array[mid] < target {
            low = mid + 1
        } else {
            high = mid - 1
        }
    }
    return nil
}

Sorting Algorithms

1. Bubble Sort

  • Time Complexity: O(n²)

  • Stable and simple but inefficient for large data sets

func bubbleSort<T: Comparable>(_ array: inout [T]) {
    for i in 0..<array.count {
        for j in 0..<array.count - i - 1 {
            if array[j] > array[j + 1] {
                array.swapAt(j, j + 1)
            }
        }
    }
}

2. Insertion Sort

  • Time Complexity: O(n²)

  • Good for small or nearly sorted data sets

func insertionSort<T: Comparable>(_ array: inout [T]) {
    for i in 1..<array.count {
        var j = i
        let key = array[j]
        while j > 0 && array[j - 1] > key {
            array[j] = array[j - 1]
            j -= 1
        }
        array[j] = key
    }
}

3. Merge Sort

  • Time Complexity: O(n log n)

  • Stable and efficient, uses extra space

func mergeSort<T: Comparable>(_ array: [T]) -> [T] {
    guard array.count > 1 else { return array }

    let middle = array.count / 2
    let left = mergeSort(Array(array[0..<middle]))
    let right = mergeSort(Array(array[middle..<array.count]))

    return merge(left, right)
}

private func merge<T: Comparable>(_ left: [T], _ right: [T]) -> [T] {
    var result: [T] = []
    var i = 0, j = 0

    while i < left.count && j < right.count {
        if left[i] <= right[j] {
            result.append(left[i])
            i += 1
        } else {
            result.append(right[j])
            j += 1
        }
    }

    return result + left[i...] + right[j...]
}

4. Quick Sort

  • Time Complexity: O(n log n) average, O(n²) worst

  • Fast and commonly used

func quickSort<T: Comparable>(_ array: [T]) -> [T] {
    guard array.count > 1 else { return array }

    let pivot = array[array.count / 2]
    let less = array.filter { $0 < pivot }
    let equal = array.filter { $0 == pivot }
    let greater = array.filter { $0 > pivot }

    return quickSort(less) + equal + quickSort(greater)
}

When to Use Each Algorithm

Algorithm

Best For

Linear Search

Small or unsorted datasets

Binary Search

Fast search on sorted data

Bubble Sort

Educational use, rarely in practice

Insertion Sort

Nearly sorted or small datasets

Merge Sort

Stable sort with consistent speed

Quick Sort

Fast, in-place sorting (average case)

Summary

Mastering these searching and sorting algorithms gives you the tools to solve a wide range of programming problems. While Swift’s sort() is optimized under the hood, knowing the mechanics behind these algorithms deepens your understanding and helps in performance-critical or educational scenarios.

Docs
Copyright © Mitch Lang. All rights reserved.