Introducción a los Algoritmos y Estructuras de Datos en C#
Los algoritmos y las estructuras de datos son la base sobre la cual se construye cualquier software de calidad. En el ecosistema .NET y el lenguaje C#, comprender estos conceptos te permite no solo escribir código más eficiente, sino también elegir competentemente las herramientas de la rica biblioteca estándar (BCL — Base Class Library). La velocidad de una aplicación, el consumo de memoria y, en última instancia, la experiencia del usuario dependen de la elección de la estructura de datos.
En este artículo, desglosaremos las estructuras de datos y los algoritmos clave que todo desarrollador de C# debería conocer. Analizaremos su implementación, características de rendimiento (notación Big O) y ejemplos prácticos de código. El artículo es adecuado tanto para principiantes como para programadores experimentados que buscan sistematizar sus conocimientos.
Estructuras de Datos Básicas en C#
Arrays y Listas (Array vs List<T>)
Array es una estructura de datos de tamaño fijo que almacena elementos del mismo tipo en una región de memoria contigua. El acceso por índice ocurre en O(1), pero insertar y eliminar elementos (excepto al final) requiere O(n) debido al desplazamiento.
int[] numbers = new int[5] { 10, 20, 30, 40, 50 };Console.WriteLine(numbers[2]); // 30List<T> es un array dinámico. Aumenta automáticamente su capacidad cuando se añaden elementos. Internamente, utiliza un array, por lo que la velocidad de acceso por índice también es O(1). Sin embargo, la inserción en el medio o al principio es O(n).
List<string> names = new List<string>() { "Anna", "Boris" };names.Add("Victor");names.Insert(1, "Gleb"); // O(n)Console.WriteLine(names[0]); // AnnaPila y Cola (Stack<T> y Queue<T>)
Stack<T> funciona bajo el principio LIFO (Last In, First Out). Se utiliza para algoritmos de recorrido, análisis de expresiones y gestión de llamadas.
Stack<int> stack = new Stack<int>();stack.Push(1);stack.Push(2);stack.Push(3);int top = stack.Pop(); // 3Queue<T> funciona bajo el principio FIFO (First In, First Out). Se utiliza en sistemas de procesamiento de tareas y almacenamiento en búfer de datos.
Queue<string> queue = new Queue<string>();queue.Enqueue("Task 1");queue.Enqueue("Task 2");string next = queue.Dequeue(); // "Task 1"Ambas estructuras están implementadas basadas en un array (buffer circular) y proporcionan operaciones de inserción y eliminación en O(1) en promedio.
Diccionario (Dictionary<TKey, TValue>)
Dictionary<TKey, TValue> es una tabla hash. Proporciona búsqueda, inserción y eliminación de elementos por clave en O(1) en promedio (con una buena función hash). Esta es una de las estructuras de datos más utilizadas en C#.
Dictionary<string, int> ages = new Dictionary<string, int>();ages["Alice"] = 30;ages["Bob"] = 25;
if (ages.ContainsKey("Alice")){ Console.WriteLine(ages["Alice"]); // 30}Importante: Las claves en un Dictionary deben ser únicas e implementar la interfaz IEquatable<T> o tener los métodos GetHashCode() y Equals() correctamente sobrescritos.
Lista Enlazada (LinkedList<T>)
LinkedList<T> es una lista doblemente enlazada. A diferencia de List, la inserción y eliminación en el medio de la lista se realiza en O(1) (si tienes una referencia al nodo). Sin embargo, el acceso por índice es O(n). Se utiliza con menos frecuencia, pero es indispensable para colas dobles y cachés LRU.
LinkedList<int> list = new LinkedList<int>();list.AddLast(1);list.AddLast(2);list.AddFirst(0);
LinkedListNode<int> node = list.Find(1);list.AddAfter(node, 10); // O(1)Algoritmos de Ordenación y Búsqueda en C#
QuickSort
QuickSort