Алгоритмы и структуры данных на Swift: полное руководство

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Алгоритмы и структуры данных на Swift: от новичка до профессионала

Swift — мощный и интуитивный язык программирования от Apple, используемый для разработки приложений под iOS, macOS, watchOS и tvOS. Понимание алгоритмов и структур данных — фундамент, который отличает опытного разработчика от новичка. В этой статье мы разберём ключевые концепции с практическими примерами на Swift.

1. Базовые структуры данных в Swift

Стандартная библиотека Swift предоставляет несколько встроенных структур, которые лежат в основе любого приложения.

Массивы (Array)

Упорядоченная коллекция элементов одного типа. Поддерживает произвольный доступ по индексу.

var numbers: [Int] = [10, 20, 30, 40, 50]
numbers.append(60)
numbers.insert(5, at: 0)
print(numbers[2]) // Вывод: 30

Словари (Dictionary)

Коллекция пар «ключ-значение» для быстрого поиска данных по уникальному ключу.

var userScores: [String: Int] = ["Alice": 95, "Bob": 87]
userScores["Charlie"] = 92
if let score = userScores["Alice"] {
    print("Alice's score: \(score)")
}

Множества (Set)

Неупорядоченная коллекция уникальных элементов. Идеально для проверки наличия или удаления дубликатов.

let fruits: Set = ["Apple", "Banana", "Orange", "Apple"]
print(fruits.count) // Вывод: 3 (дубликат удалён)

2. Реализация стека и очереди на Swift

Стек и очередь — классические структуры данных, которые часто реализуются поверх массивов.

Стек (Stack) — LIFO (Last In, First Out)

Элементы добавляются и удаляются с одного конца.

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()!) // Вывод: 3

Очередь (Queue) — FIFO (First In, First Out)

Элементы добавляются в конец, а удаляются из начала.

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()!) // Вывод: First

3. Алгоритмы сортировки и поиска

Рассмотрим два фундаментальных алгоритма, которые полезны в реальных проектах.

Быстрая сортировка (Quick Sort)

Эффективный алгоритм «разделяй и властвуй» со средней сложностью 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)) // Вывод: [1, 1, 2, 3, 6, 8, 10]

Бинарный поиск (Binary Search)

Работает только на отсортированном массиве. Сложность 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) {
    print("Found at index: \(index)") // Вывод: Found at index: 3
}

4. Связный список (Linked List) — кастомная реализация

Связный список не входит в стандартную библиотеку Swift, но его легко реализовать самостоятельно.

class Node<T> {
    var value: T
    var next: Node?
    
    init(value: T) {
        self.value = value
    }
}

class LinkedList<T> {
    var head: Node<T>?
    
    func append(_ value: T) {
        let newNode = Node(value: value)
        if head == nil {
            head = newNode
            return
        }
        var current = head
        while current?.next != nil {
            current = current?.next
        }
        current?.next = newNode
    }
    
    func printList() {
        var current = head
        while current != nil {
            print(current!.value, terminator: " -> ")
            current = current?.next
        }
        print("nil")
    }
}

let list = LinkedList<Int>()
list.append(10)
list.append(20)
list.append(30)
list.printList() // Вывод: 10 -> 20 -> 30 -> nil

Заключение

Освоение алгоритмов и структур данных на Swift — ключевой шаг к написанию эффективного и масштабируемого кода для iOS и macOS. В этой статье мы рассмотрели:

  • Встроенные структуры: Array, Dictionary, Set.
  • Реализацию стека и очереди.
  • Алгоритмы сортировки (Quick Sort) и поиска (Binary Search).
  • Создание связного списка с нуля.

Практикуйтесь, экспериментируйте с кодом и внедряйте эти паттерны в свои проекты. Чем глубже вы понимаете структуры данных, тем увереннее чувствуете себя при решении сложных задач. Удачи в разработке!

Блоги

Рекомендаций по книгам