Algorithms and Data Structures in Swift: From Beginner to Professional
Swift is a powerful and intuitive programming language from Apple, used for developing applications for iOS, macOS, watchOS, and tvOS. Understanding algorithms and data structures is the foundation that distinguishes an experienced developer from a beginner. In this article, we will break down key concepts with practical examples in Swift.
1. Basic Data Structures in Swift
The Swift standard library provides several built-in structures that form the basis of any application.
Arrays (Array)
An ordered collection of elements of the same type. Supports random access by index.
var numbers: [Int] = [10, 20, 30, 40, 50]numbers.append(60)numbers.insert(5, at: 0)print(numbers[2]) // Output: 30Dictionaries (Dictionary)
A collection of key-value pairs for quickly finding data by a unique key.
var userScores: [String: Int] = ["Alice": 95, "Bob": 87]userScores["Charlie"] = 92if let score = userScores["Alice"] { print("Alice's score: \\(score)")}Sets (Set)
An unordered collection of unique elements. Ideal for checking membership or removing duplicates.
let fruits: Set = ["Apple", "Banana", "Orange", "Apple"]print(fruits.count) // Output: 3 (duplicate removed)2. Implementing Stack and Queue in Swift
Stack and Queue are classic data structures that are often implemented on top of arrays.
Stack — LIFO (Last In, First Out)
Elements are added and removed from one end.
struct Stack<T> { private var elements: [T] = [] mutating func push(_ value: T) { elements.append(value) } mutating func pop() -> T? { return elements.popLast() } func peek() -> T? { return elements.last }}
var stack = Stack<Int>()stack.push(1)stack.push(2)stack.push(3)print(stack.pop()!) // Output: 3Queue — FIFO (First In, First Out)
Elements are added to the end and removed from the beginning.
struct Queue<T> { private var elements: [T] = [] mutating func enqueue(_ value: T) { elements.append(value) } mutating func dequeue() -> T? { return elements.isEmpty ? nil : elements.removeFirst() }}
var queue = Queue<String>()queue.enqueue("First")queue.enqueue("Second")print(queue.dequeue()!) // Output: First3. Sorting and Searching Algorithms
Let's look at two fundamental algorithms that are useful in real-world projects.
Quick Sort
An efficient divide-and-conquer algorithm with an average complexity of O(n log n).
func quickSort(_ array: [Int]) -> [Int] { 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)}
let unsorted = [3, 6, 8, 10, 1, 2, 1]print(quickSort(unsorted)) // Output: [1, 1, 2, 3, 6, 8, 10]Binary Search
Works only on a sorted array. Complexity is O(log n).
func binarySearch(_ array: [Int], target: Int) -> Int? { var low = 0 var high = array.count - 1 while low <= high { let mid = (low + high) / 2 if array[mid] == target { return mid } else if array[mid] < target { low = mid + 1 } else { high = mid - 1 } } return nil}
let sortedArray = [1, 3, 5, 7, 9, 11]if let index = binarySearch(sortedArray, target: 7) { p