Algoritmos y estructuras de datos en Swift: en la práctica
Swift es un lenguaje de programación potente e intuitivo creado por Apple para el desarrollo en iOS, macOS, watchOS y tvOS. Sin embargo, conocer la sintaxis y los frameworks es solo la mitad del éxito. Para escribir aplicaciones eficientes, rápidas y escalables, es necesario comprender cómo funcionan los algoritmos y las estructuras de datos. En este artículo, analizaremos conceptos clave con ejemplos concretos de código en Swift. Aprenderás cómo implementar una pila, una cola, algoritmos de ordenamiento y búsqueda binaria, y dónde se aplican estos conocimientos en el desarrollo real.
Pila (Stack) en Swift: LIFO en acción
Una pila es una colección que funciona bajo el principio "último en entrar, primero en salir" (LIFO). Imagina una pila de platos: solo tomas el de arriba. En iOS, la pila se utiliza, por ejemplo, para la navegación (UINavigationController) o para deshacer acciones (Undo).
Implementamos una pila en 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 }}
// Ejemplo de usovar stack = Stack<String>()stack.push("Primero")stack.push("Segundo")stack.push("Tercero")
print(stack.pop()!) // Terceroprint(stack.peek()!) // Segundo¿Dónde se aplica? En aplicaciones para mostrar el historial de navegación, en analizadores sintácticos (verificación de paréntesis), en algoritmos de recorrido de grafos (DFS).
Cola (Queue): FIFO para procesamiento de tareas
Una cola funciona bajo el principio "primero en entrar, primero en salir" (FIFO). Como una cola en una tienda: el primero que llega es el primero en ser atendido. En Swift, la cola se usa a menudo para gestionar tareas (DispatchQueue), procesar solicitudes de red o animaciones.
Implementación básica de una cola:
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 }}
// Ejemplo de usovar queue = Queue<Int>()queue.enqueue(1)queue.enqueue(2)queue.enqueue(3)
print(queue.dequeue()!) // 1print(queue.front()!) // 2Problema de rendimiento: removeFirst() en un array tiene complejidad O(n), ya que todos los elementos se desplazan. Para alto rendimiento, usa ContiguousArray o una cola bidireccional (deque). En proyectos reales, Apple recomienda DispatchQueue para concurrencia.
Algoritmos de ordenamiento: de burbuja a ordenamiento rápido
El ordenamiento es una de las operaciones más comunes. Swift tiene un sort() incorporado, pero comprender los mecanismos internos te ayudará a elegir el algoritmo óptimo para cada tarea.
Ordenamiento de burbuja (Bubble Sort) — O(n²)
Un algoritmo simple pero lento. Útil para aprender, pero no para producción.
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 =