9 - Buenas prácticas de programación en C

Estas pautas ayudan a escribir y depurar implementaciones de MergeSort, QuickSort y HeapSort de forma robusta. Aplica los puntos siguientes para evitar errores comunes y mejorar la mantenibilidad.

9.1 Modularizar para mejorar la claridad

  • Separa algoritmos y utilidades en archivos propios (mergesort.c, quicksort.c, heapsort.c, sort.h).
  • Mantén las funciones auxiliares (impresión, copia, generación de datos) en un módulo compartido.
  • Evita duplicar código: reutiliza helpers en todas las implementaciones.

9.2 Manejo correcto de memoria

  • En MergeSort, reserva el buffer una sola vez y libera al final; valida siempre el resultado de malloc.
  • En QuickSort, cuida la pila: usa pivote aleatorio/mediana de tres y límite de recursión si el stack es reducido.
  • En HeapSort, todo es in-place; evita asignaciones innecesarias y garantiza que los índices no se salgan del rango.

9.3 Evitar recursión profunda

  • QuickSort: cambia a Insertion Sort en subarrays pequeños y limita la profundidad (estrategia introsort).
  • MergeSort: si el stack es crítico, considera la variante bottom-up iterativa.
  • HeapSort: mantiene control iterativo, úsalo si la pila es un recurso limitado.

9.4 Comentar adecuadamente

  • Comenta decisiones no obvias: elección de pivote, tamaño de corte a Insertion Sort, uso de buffers.
  • Evita comentarios redundantes que repitan lo que el código ya indica.
  • Documenta precondiciones y rangos esperados de los parámetros.

9.5 Evitar accesos fuera de rango

  • Valida n antes de ordenar; si n <= 1, retorna de inmediato.
  • En QuickSort, revisa los índices devueltos por la partición para no re-entrar en segmentos vacíos.
  • En HeapSort, ajusta el límite lógico tras cada extracción antes de llamar a sift_down.

9.6 Testing con casos pequeños antes de casos grandes

  • Prueba arrays vacíos, de un elemento, ordenados, inversos y con duplicados.
  • Usa semillas fijas al generar aleatorios para reproducir resultados.
  • Verifica estabilidad cuando aplique (MergeSort) con elementos duplicados.

9.7 Uso de CLion: breakpoints y análisis paso a paso

  • Coloca breakpoints en la mezcla de MergeSort, la partición de QuickSort y el sift_down de HeapSort.
  • Observa las variables de índice y el estado del array tras cada paso.
  • Habilita inspección de pila para detectar recursiones profundas inesperadas.

9.8 Errores frecuentes a evitar

  • Intercambiar mal el pivote en QuickSort y perder el elemento de referencia.
  • Olvidar copiar de vuelta el buffer en MergeSort, dejando resultados parciales.
  • No reducir el rango del heap en HeapSort, reintroduciendo elementos ya ordenados.

9.9 Logging y métricas

  • Imprime solo los primeros/últimos elementos en arrays grandes para evitar ruido.
  • Guarda tiempos y, si es posible, conteo de comparaciones/intercambios para comparar versiones.
  • Incluye información de configuración (tamaño de entrada, semilla) al registrar resultados.

9.10 Estabilidad y expectativas

  • Si necesitas estabilidad, elige MergeSort o adapta QuickSort con comparaciones estables (costo extra).
  • HeapSort no es estable: documenta esta característica en APIs públicas.
  • Al comparar resultados, revisa el orden relativo de duplicados para validar estabilidad.