Swift Program to Implement Merge Sort

Swift Program to Implement Merge Sort

Merge sort is a powerful and important sorting algorithm that many beginners eventually grow to appreciate because of its clean and predictable structure. Unlike simpler sorting methods such as insertion sort or bubble sort, merge sort works by dividing the list into smaller halves, sorting those halves, and then combining them in a careful and ordered way. This method follows the idea of “divide and conquer,” which is a common strategy used in many advanced algorithms. Once you understand merge sort, it becomes easier to learn other strong algorithms later on.

Pluralsight Logo
Accelerate your tech career
with hands-on learning.
Whether you're a tech newbie or a total pro,
get the skills and confidence to land your next move.
Start 10-Day Free Trial

What makes merge sort special is its speed and reliability, especially when dealing with large amounts of data. It is used in real systems where efficiency matters, such as search engines, databases, and software tools that manage large lists. Even though the idea may feel slightly different from the usual step-by-step sorting, merge sort is friendly once you break it down. The best part is that Swift can express the algorithm in a very clear way, making it perfect for beginners who want to grow their confidence.

Program 1: Basic Merge Sort Using Recursion

This first program shows the classic version of merge sort using recursion. It splits the array into halves, sorts each half, and then merges them again in sorted order. This helps beginners see the natural flow of divide, sort, and join.

import Foundation

func mergeSort(_ arr: [Int]) -> [Int] {

    if arr.count <= 1 {
        return arr
    }

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

    return merge(left, right)

}

func merge(_ left: [Int], _ right: [Int]) -> [Int] {

    var merged: [Int] = []
    var i = 0
    var j = 0

    while i < left.count && j < right.count {

        if left[i] <= right[j] {
            merged.append(left[i])
            i += 1
        } else {
            merged.append(right[j])
            j += 1
        }

    }

    merged.append(contentsOf: left[i...])
    merged.append(contentsOf: right[j...])

    return merged

}

let data = [38, 27, 43, 3, 9, 82, 10]
let sorted = mergeSort(data)

print("Sorted Array:", sorted)

This version works by repeatedly cutting the array in half until each piece has one element. Once the pieces are tiny, they are merged step by step into sorted order. Beginners understand this approach well because the splitting and merging feel natural once seen in action.

Program 2: Merge Sort With a Clearer Merge Function

This program uses the same idea but rewrites the merge function in a more beginner-friendly way. It improves readability so you can focus on how the merging actually happens. The main merge sort function stays the same.

import Foundation

func mergeSort2(_ arr: [Int]) -> [Int] {

    if arr.count < 2 {
        return arr
    }

    let mid = arr.count / 2
    let left = mergeSort2(Array(arr[0..<mid]))
    let right = mergeSort2(Array(arr[mid..<arr.count]))

    return mergeSimple(left, right)

}

func mergeSimple(_ left: [Int], _ right: [Int]) -> [Int] {

    var L = left
    var R = right
    var result: [Int] = []

    while !L.isEmpty && !R.isEmpty {

        if L.first! <= R.first! {
            result.append(L.removeFirst())
        } else {
            result.append(R.removeFirst())
        }

    }

    result.append(contentsOf: L)
    result.append(contentsOf: R)

    return result

}

let list = [20, 7, 1, 54, 23]
let output = mergeSort2(list)

print("Sorted Array:", output)

This method helps beginners understand merging by using clear variable names and removing elements from the front. Even though removing from the front is not the fastest method, it is very easy to understand, which makes it perfect for learners.

Program 3: Merge Sort in Descending Order

This program sorts values from highest to lowest instead of lowest to highest. The change happens inside the comparison, showing how flexible merge sort can be with only small adjustments.

import Foundation

func mergeSortDescending(_ arr: [Int]) -> [Int] {

    if arr.count <= 1 {
        return arr
    }

    let mid = arr.count / 2
    let left = mergeSortDescending(Array(arr[0..<mid]))
    let right = mergeSortDescending(Array(arr[mid..<arr.count]))

    return mergeDescending(left, right)

}

func mergeDescending(_ left: [Int], _ right: [Int]) -> [Int] {

    var L = left
    var R = right
    var result: [Int] = []

    while !L.isEmpty && !R.isEmpty {

        if L.first! >= R.first! {
            result.append(L.removeFirst())
        } else {
            result.append(R.removeFirst())
        }

    }

    result.append(contentsOf: L)
    result.append(contentsOf: R)

    return result

}

let values = [5, 12, 3, 19, 7]
let sortedDesc = mergeSortDescending(values)

print("Sorted Descending:", sortedDesc)

This version is useful when you want high scores or large numbers first. It also shows beginners how algorithms can shift direction with very small changes in the logic.

Program 4: Merge Sort Using a Single Merge Function With Indices

This version avoids removing elements or slicing arrays. Instead, it uses index pointers, which is closer to how merge sort works efficiently in real systems. It uses recursion but in a way that saves memory.

import Foundation

func mergeSortIndex(_ arr: inout [Int], _ temp: inout [Int], _ left: Int, _ right: Int) {

    if left >= right {
        return
    }

    let mid = (left + right) / 2

    mergeSortIndex(&arr, &temp, left, mid)
    mergeSortIndex(&arr, &temp, mid + 1, right)
    mergeIndex(&arr, &temp, left, mid, right)

}

func mergeIndex(_ arr: inout [Int], _ temp: inout [Int], _ left: Int, _ mid: Int, _ right: Int) {

    var i = left
    var j = mid + 1
    var k = left

    while i <= mid && j <= right {

        if arr[i] <= arr[j] {
            temp[k] = arr[i]
            i += 1
        } else {
            temp[k] = arr[j]
            j += 1
        }

        k += 1

    }

    while i <= mid {
        temp[k] = arr[i]
        i += 1
        k += 1
    }

    while j <= right {
        temp[k] = arr[j]
        j += 1
        k += 1
    }

    for n in left...right {
        arr[n] = temp[n]
    }

}

var numbers = [31, 41, 59, 26, 53, 58]
var temp = Array(repeating: 0, count: numbers.count)

mergeSortIndex(&numbers, &temp, 0, numbers.count - 1)

print("Sorted Array:", numbers)

This method is more efficient because it minimizes memory usage. Beginners who want to move to a more advanced style will appreciate how this form looks more like a professional algorithm.

Program 5: Merge Sort Using an Iterative Approach

This final program shows merge sort without recursion. Instead, it merges small pieces first, then bigger pieces, until the whole array becomes sorted. This gives beginners another way to understand the algorithm.

import Foundation

func mergeIndex(_ arr: inout [Int], _ temp: inout [Int], _ left: Int, _ mid: Int, _ right: Int) {

    var i = left
    var j = mid + 1
    var k = left

    while i <= mid && j <= right {

        if arr[i] <= arr[j] {
            temp[k] = arr[i]
            i += 1
        } else {
            temp[k] = arr[j]
            j += 1
        }

        k += 1

    }

    while i <= mid {
        temp[k] = arr[i]
        i += 1
        k += 1
    }

    while j <= right {
        temp[k] = arr[j]
        j += 1
        k += 1
    }

    for n in left...right {
        arr[n] = temp[n]
    }

}

func iterativeMergeSort(_ arr: [Int]) -> [Int] {

    var nums = arr
    var temp = arr
    var size = 1

    while size < nums.count {

        var left = 0

        while left < nums.count - size {

            let mid = left + size - 1
            let right = min(left + 2 * size - 1, nums.count - 1)

            mergeIndex(&nums, &temp, left, mid, right)

            left += 2 * size

        }

        size *= 2

    }

    return nums

}

let dataSet = [32, 7, 4, 90, 22, 16]
let finalSorted = iterativeMergeSort(dataSet)

print("Sorted Array:", finalSorted)

This version helps beginners see how merge sort can work without recursion. Instead of splitting the array first, it builds the sorted result from smaller sorted parts. It is a nice way to understand the same idea through a different lens.

Frequently Asked Questions (FAQ)

This section explains common questions students often ask when learning merge sort.

Q1: Why is merge sort considered efficient?
It handles large data well because it works in a predictable time and follows the divide-and-conquer method.

Q2: Does merge sort always use extra memory?
Yes, most versions need extra space to store merged results, making it stable but memory-aware.

Q3: Is merge sort faster than bubble sort or insertion sort?
Yes, it usually performs much better, especially with large datasets.

Q4: Can merge sort work with negative numbers?
It works with any numbers because it only compares values.

Q5: Which version should beginners start with?
The basic recursive version is usually the easiest and clearest for new learners.

Conclusion

Merge sort may look different from the simpler sorting algorithms, but once you understand its rhythm of splitting and merging, it becomes clear and enjoyable. It teaches strong ideas like divide-and-conquer, recursion, and careful merging. The Swift programs above show several ways to express the same algorithm, helping you grow from beginner level into someone comfortable with deeper concepts. Keep practicing, try new arrays, and experiment with your own variations. With time, merge sort will feel natural, and you will be ready to explore even more advanced sorting techniques.

Scroll to Top