Algoritmos y estructuras de datos en Kotlin: de la teoría a la práctica
Kotlin es un lenguaje de programación moderno que combina la concisión de Python y la potencia de Java. Para escribir código eficiente, es necesario comprender cómo funcionan los algoritmos y las estructuras de datos. En este artículo, analizaremos los conceptos clave con ejemplos en Kotlin que te ayudarán a escribir programas rápidos y confiables.
El material será útil tanto para principiantes como para desarrolladores que deseen sistematizar sus conocimientos. Todos los ejemplos se pueden ejecutar en el entorno IntelliJ IDEA o en un compilador en línea.
1. Estructuras de datos básicas en Kotlin
La biblioteca estándar de Kotlin proporciona un rico conjunto de estructuras de datos. Veamos las principales.
Listas (List, MutableList)
Las listas son colecciones ordenadas de elementos. Kotlin distingue entre listas mutables e inmutables.
fun main() { // Lista inmutable val fruits = listOf("Manzana", "Banana", "Naranja") // Lista mutable val numbers = mutableListOf(1, 2, 3) numbers.add(4) numbers.removeAt(1) println(fruits[0]) // Manzana println(numbers) // [1, 3, 4]}Conjuntos (Set, MutableSet)
Los conjuntos almacenan elementos únicos. Son útiles para verificar duplicados.
fun main() { val uniqueNumbers = setOf(1, 2, 2, 3, 3, 3) println(uniqueNumbers) // [1, 2, 3] val mutableSet = mutableSetOf("a", "b") mutableSet.add("c") println(mutableSet.contains("b")) // true}Diccionarios (Map, MutableMap)
Los diccionarios almacenan pares clave-valor. Son el equivalente de una tabla hash.
fun main() { val capitals = mapOf( "Rusia" to "Moscú", "EE.UU." to "Washington", "Francia" to "París" ) println(capitals["Rusia"]) // Moscú // Diccionario mutable val scores = mutableMapOf("Iván" to 85) scores["María"] = 92 scores["Iván"] = 90}2. Implementación de estructuras de datos clásicas
A veces las estructuras estándar no son suficientes. Veamos cómo implementar una pila y una cola manualmente.
Pila (Stack)
La pila funciona bajo el principio LIFO (Last In, First Out). Se utiliza en analizadores sintácticos, deshacer acciones y recorrido de grafos.
class Stack<T> { private val elements = mutableListOf<T>() fun push(item: T) = elements.add(item) fun pop(): T? = if (isEmpty()) null else elements.removeAt(elements.size - 1) fun peek(): T? = elements.lastOrNull() fun isEmpty() = elements.isEmpty() fun size() = elements.size}
fun main() { val stack = Stack<Int>() stack.push(10) stack.push(20) stack.push(30) println(stack.pop()) // 30 println(stack.peek()) // 20 println(stack.size()) // 2}Cola (Queue)
La cola funciona bajo el principio FIFO (First In, First Out). Se utiliza en sistemas de procesamiento de tareas.
class Queue<T> { private val elements = mutableListOf<T>() fun enqueue(item: T) = elements.add(item) fun dequeue(): T? = if (isEmpty()) null else elements.removeAt(0) fun peek(): T? = elements.firstOrNull() fun isEmpty() = elements.isEmpty()}
fun main() { val queue = Queue<String>() queue.enqueue("Tarea 1") queue.enqueue("Tarea 2") queue.enqueue("Tarea 3") println(queue.dequeue()) // Tarea 1 println(queue.peek()) // Tarea 2}3. Algoritmos de ordenamiento en Kotlin
El ordenamiento es una operación básica. Analicemos tres algoritmos populares.
Ordenamiento rápido (QuickSort)
Uno de los algoritmos más eficientes con una complejidad promedio de O(n log n).
fun quickSort(arr: IntArray, low: Int, high: Int) { if (low < high) { val pi = partition(arr, low, high) quickSort(arr, low, pi - 1) quick