Algoritmos e Estruturas de Dados em Swift: na prática
Swift é uma linguagem de programação poderosa e intuitiva, criada pela Apple para desenvolvimento em iOS, macOS, watchOS e tvOS. No entanto, conhecer a sintaxe e os frameworks é apenas metade do sucesso. Para escrever aplicações eficientes, rápidas e escaláveis, é necessário entender como funcionam os algoritmos e as estruturas de dados. Neste artigo, vamos analisar os conceitos-chave com exemplos concretos de código em Swift. Você aprenderá como implementar pilha, fila, algoritmos de ordenação e busca binária, e onde esses conhecimentos são aplicados no desenvolvimento real.
Pilha (Stack) em Swift: LIFO em ação
Uma pilha é uma coleção que funciona pelo princípio "último a entrar, primeiro a sair" (LIFO). Imagine uma pilha de pratos: você pega apenas o de cima. No iOS, a pilha é usada, por exemplo, para navegação (UINavigationController) ou para desfazer ações (Undo).
Vamos implementar uma pilha em Swift usando genéricos:
struct Stack<Element> { private var elements: [Element] = [] mutating func push(_ element: Element) { elements.append(element) } @discardableResult mutating func pop() -> Element? { return elements.popLast() } func peek() -> Element? { return elements.last } var isEmpty: Bool { return elements.isEmpty } var count: Int { return elements.count }}
// Exemplo de usovar stack = Stack<String>()stack.push("Primeiro")stack.push("Segundo")stack.push("Terceiro")
print(stack.pop()!) // Terceiroprint(stack.peek()!) // SegundoOnde é aplicado? Em aplicações para exibir histórico de visualizações, em parsers (verificação de parênteses), em algoritmos de travessia de grafos (DFS).
Fila (Queue): FIFO para processamento de tarefas
A fila funciona pelo princípio "primeiro a entrar, primeiro a sair" (FIFO). Como uma fila na loja: quem chega primeiro é atendido primeiro. Em Swift, a fila é frequentemente usada para gerenciar tarefas (DispatchQueue), processar requisições de rede ou animações.
Implementação básica de uma fila:
struct Queue<Element> { private var elements: [Element] = [] mutating func enqueue(_ element: Element) { elements.append(element) } @discardableResult mutating func dequeue() -> Element? { return isEmpty ? nil : elements.removeFirst() } func front() -> Element? { return elements.first } var isEmpty: Bool { return elements.isEmpty } var count: Int { return elements.count }}
// Exemplo de usovar queue = Queue<Int>()queue.enqueue(1)queue.enqueue(2)queue.enqueue(3)
print(queue.dequeue()!) // 1print(queue.front()!) // 2Problema de desempenho: removeFirst() em um array tem complexidade O(n), pois todos os elementos são deslocados. Para alto desempenho, use ContiguousArray ou uma fila dupla (deque). Em projetos reais, a Apple recomenda DispatchQueue para multithreading.
Algoritmos de ordenação: da bolha à ordenação rápida
Ordenação é uma das operações mais comuns. Em Swift existe o método nativo sort(), mas entender os mecanismos internos ajuda você a escolher o algoritmo ideal para cada tarefa específica.
Ordenação bolha (Bubble Sort) — O(n²)
Um algoritmo simples, mas lento. Útil para aprendizado, mas não para produção.
func bubbleSort(_ array: inout [Int]) { guard array.count > 1 else { return } for i in 0..<array.count { var swapped = false for j in 0..<(array.count - 1 - i) { if array[j] > array[j + 1] { array.swapAt(j, j + 1) swapped =