0

Estructuras de Datos en C# 02: Complejidad Algorítmica – Big O Notation

Introducción a la clase

En esta clase aprenderemos sobre la complejidad algorítmica, un concepto fundamental para medir la eficiencia de un algoritmo. Analizaremos cómo se mide el rendimiento del código usando la Notación Big O y cómo impacta en el desarrollo de software en C#.

¿Qué obtendrás de esta clase?

  • Comprender qué es la complejidad algorítmica y su importancia.
  • Aprender a medir la eficiencia de un algoritmo con Big O Notation.
  • Identificar los diferentes tipos de complejidad.
  • Implementar ejemplos en C# para visualizar su impacto.

¿Qué es la Complejidad Algorítmica?

La complejidad algorítmica mide cuántos recursos (tiempo y memoria) necesita un algoritmo para ejecutarse en función del tamaño de la entrada. Un algoritmo eficiente es aquel que resuelve un problema rápidamente y sin consumir demasiada memoria.

Ejemplo en la vida real:

  • Buscar un libro en una biblioteca desordenada (requiere más tiempo).
  • Buscar un libro en una biblioteca organizada alfabéticamente (requiere menos tiempo).

En programación, el objetivo es diseñar algoritmos eficientes para optimizar el rendimiento del software.

¿Qué es la Notación Big O?

Big O Notation es una forma de expresar cómo crece el tiempo de ejecución de un algoritmo a medida que aumenta el tamaño de los datos de entrada.

Se representa como:

  • O(1) → Tiempo constante
  • O(log n) → Tiempo logarítmico
  • O(n) → Tiempo lineal
  • O(n log n) → Tiempo logarítmico lineal
  • O(n²) → Tiempo cuadrático
  • O(2^n) → Tiempo exponencial
  • O(n!) → Tiempo factorial

Ejemplo de cómo crece el tiempo de ejecución en diferentes complejidades:

Tamaño de Entrada (n)O(1)O(log n)O(n)O(n log n)O(n²)
10131030100
1001610060010,000
1000110100010,0001,000,000

Entre más grande es «n», más impacta la elección del algoritmo en el rendimiento.

Ejemplos de Complejidad en C#

O(1) – Complejidad Constante

No importa el tamaño de los datos, el tiempo de ejecución siempre es el mismo.

int ObtenerPrimerElemento(int[] numeros)
{
    return numeros[0]; // Siempre toma la primera posición
}

O(n) – Complejidad Lineal

El tiempo de ejecución crece proporcionalmente al tamaño de los datos.

void ImprimirNumeros(int[] numeros)
{
    foreach (var num in numeros)
    {
        Console.WriteLine(num); // Se ejecuta una vez por cada número
    }
}

O(n²) – Complejidad Cuadrática

Se ejecutan múltiples ciclos anidados, aumentando el tiempo exponencialmente.

void ImprimirPares(int[] numeros)
{
    for (int i = 0; i < numeros.Length; i++)
    {
        for (int j = 0; j < numeros.Length; j++)
        {
            Console.WriteLine(numeros[i] + ", " + numeros[j]); // Ejecuta todas las combinaciones
        }
    }
}

Caso de uso real

Los motores de búsqueda como Google aplican algoritmos eficientes para mostrar resultados en milisegundos. Un algoritmo ingenuo que revisara todas las páginas web de manera secuencial (O(n)) tardaría demasiado. En su lugar, usan algoritmos eficientes como árboles de búsqueda y estructuras hash (O(log n) o O(1)) para indexar y recuperar información rápidamente.

Ejemplo en C#: Algoritmo de búsqueda eficiente con Diccionario (O(1))

using System;
using System.Collections.Generic;

class BusquedaRapida
{
    static void Main()
    {
        Dictionary<string, string> diccionario = new Dictionary<string, string>
        {
            { "C#", "Lenguaje de programación de Microsoft" },
            { "Python", "Lenguaje de alto nivel y multipropósito" },
            { "Java", "Lenguaje usado en aplicaciones empresariales" }
        };

        Console.WriteLine("Ingrese una palabra clave:");
        string clave = Console.ReadLine();

        if (diccionario.ContainsKey(clave))
        {
            Console.WriteLine("Definición: " + diccionario[clave]);
        }
        else
        {
            Console.WriteLine("Palabra no encontrada.");
        }
    }
}

Aquí, la búsqueda en un diccionario (hash table) tiene una complejidad de O(1), ya que encuentra la clave en tiempo constante sin importar cuántos elementos haya.

Desafío práctico

Ejercicio: Implementa un programa en C# que permita buscar un número en un array usando dos métodos:

  1. Búsqueda Lineal (O(n)) → Recorrer el array uno por uno.
  2. Búsqueda Binaria (O(log n)) → Usar la estrategia de dividir y conquistar.

Resumen de la clase

  • La complejidad algorítmica mide la eficiencia de un algoritmo en términos de tiempo y espacio.
  • Big O Notation nos ayuda a clasificar algoritmos según su rendimiento.
  • Se implementaron ejemplos en C# con O(1), O(n) y O(n²).
  • Se presentó un caso de uso real aplicado a motores de búsqueda.

Próxima clase: Estructuras de Datos Lineales – Arrays y Listas en C#

En la siguiente clase aprenderemos sobre Arrays y Listas en C#, su estructura interna, ventajas, desventajas y cuándo utilizar cada una para optimizar el rendimiento de nuestras aplicaciones.O

Fernando Sonego

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *