El proyecto final combina todo lo aprendido: implementar funciones con distintos órdenes de crecimiento, medir tiempos, mostrar un gráfico sencillo en consola, optimizar y ofrecer un menú de pruebas listo para compilar.
int constante(int n) { return 42; } // O(1)
int suma_lineal(const int *v, int n) { // O(n)
int total = 0;
for (int i = 0; i < n; i++) total += v[i];
return total;
}
int busca_cuadratica(const int *v, int n) { // O(n^2)
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (v[i] == v[j]) return 1;
}
}
return 0;
}
Prepara entradas de distinto tamaño para ver cómo crece el tiempo en cada función.
double medir_segundos(void (*fn)(int *v, int n), int *v, int n) {
const int rep = 2000; // repeticiones altas para ver tiempos > 0
fn(v, n); // calentamiento
clock_t inicio = clock();
for (int i = 0; i < rep; i++) fn(v, n);
clock_t fin = clock();
return (double)(fin - inicio) / (CLOCKS_PER_SEC * rep);
}
Corre cada función con varios n, guarda los pares (n, tiempo) y verifica si la curva coincide con el Big-O esperado.
void grafico_ascii(const int *ns, const double *ts, int m) {
double max = 0.0;
for (int i = 0; i < m; i++) if (ts[i] > max) max = ts[i];
for (int i = 0; i < m; i++) {
int barras = (int)((ts[i] / max) * 50); // escala a 50 caracteres
printf("%6d | ", ns[i]);
for (int j = 0; j < barras; j++) putchar('#');
printf(" %.6f s\n", ts[i]);
}
}
Este gráfico de barras da una vista rápida del crecimiento sin depender de herramientas externas.
O(n log n).O(n) promedio.int main(void) {
int opcion;
int datos_suma[200000];
int datos_busca[8000];
generar_datos(datos_suma, 200000);
generar_datos(datos_busca, 8000);
do {
printf("1) Suma lineal\n2) Buscar duplicado (cuadratico)\n3) Buscar duplicado optimizado\n0) Salir\n");
scanf("%d", &opcion);
switch (opcion) {
case 1: printf("Tiempo: %.6f s\n", medir_segundos(suma_lineal, datos_suma, 200000)); break;
case 2: printf("Tiempo: %.6f s\n", medir_segundos(busca_cuadratica_wrap, datos_busca, 8000)); break;
case 3: printf("Tiempo: %.6f s\n", medir_segundos(busca_hash_wrap, datos_busca, 8000)); break;
case 0: puts("Fin"); break;
default: puts("Opcion invalida");
}
} while (opcion != 0);
return 0;
}
Las funciones _wrap son adaptadores con la firma esperada (reciben int *v y n). Ajusta n para que cada prueba tarde un tiempo razonable.
main.c y los archivos con tus funciones.-O2 -g para equilibrar optimización y depuración.main.c: menú interactivo y orquestación de pruebas.funciones.h: declaraciones de las funciones de cada Big-O y utilidades compartidas.funciones.c: implementaciones de versiones lenta/optimizada, generación de datos y adaptadores para medir.benchmark.c: helpers de medición y exportación opcional a CSV.Makefile o configuración de CLion: flags de compilación (-O2 -g -fsanitize=address,leak en modo debug).README.md: instrucciones de ejecución, tamaños de entrada sugeridos y precauciones de memoria.resultados.csv (opcional): salidas para graficar tiempos.// funciones.h
#include <stddef.h>
void generar_datos(int *v, int n);
int constante(int n);
int suma_lineal(const int *v, int n);
int busca_cuadratica(const int *v, int n);
int busca_hash(const int *v, int n, int max_valor);
void busca_cuadratica_wrap(int *v, int n);
void busca_hash_wrap(int *v, int n);
// funciones.c
#include "funciones.h"
#include <stdlib.h>
#include <time.h>
#define MAX_VALOR 100000
void generar_datos(int *v, int n) {
srand((unsigned)time(NULL));
for (int i = 0; i < n; i++) v[i] = rand() % MAX_VALOR;
}
int constante(int n) { (void)n; return 42; }
int suma_lineal(const int *v, int n) {
int total = 0;
for (int i = 0; i < n; i++) total += v[i];
return total;
}
int busca_cuadratica(const int *v, int n) {
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (v[i] == v[j]) return 1;
}
}
return 0;
}
int busca_hash(const int *v, int n, int max_valor) {
int *tabla = calloc((size_t)max_valor, sizeof(int));
if (!tabla) return 0;
int hallado = 0;
for (int i = 0; i < n; i++) {
int clave = v[i] % max_valor;
if (tabla[clave]) { hallado = 1; break; }
tabla[clave] = 1;
}
free(tabla);
return hallado;
}
void busca_cuadratica_wrap(int *v, int n) {
(void)busca_cuadratica(v, n);
}
void busca_hash_wrap(int *v, int n) {
(void)busca_hash(v, n, MAX_VALOR);
}
// benchmark.c
#include "funciones.h"
#include <stdio.h>
#include <time.h>
double medir_segundos(void (*fn)(int *v, int n), int *v, int n) {
const int rep = 2000;
fn(v, n);
clock_t inicio = clock();
for (int i = 0; i < rep; i++) fn(v, n);
clock_t fin = clock();
return (double)(fin - inicio) / (CLOCKS_PER_SEC * rep);
}
void grafico_ascii(const int *ns, const double *ts, int m) {
double max = 0.0;
for (int i = 0; i < m; i++) if (ts[i] > max) max = ts[i];
for (int i = 0; i < m; i++) {
int barras = max == 0 ? 0 : (int)((ts[i] / max) * 50);
printf("%6d | ", ns[i]);
for (int j = 0; j < barras; j++) putchar('#');
printf(" %.6f s\n", ts[i]);
}
}
void escribir_csv(const char *ruta, const int *ns, const double *ts, int m) {
FILE *f = fopen(ruta, "w");
if (!f) return;
fprintf(f, "n,tiempo_s\n");
for (int i = 0; i < m; i++) fprintf(f, "%d,%.6f\n", ns[i], ts[i]);
fclose(f);
}
// main.c
#include "funciones.h"
#include <stdio.h>
double medir_segundos(void (*fn)(int *v, int n), int *v, int n); // declarado en benchmark.c
int main(void) {
int opcion;
int datos_suma[200000];
int datos_busca[8000];
generar_datos(datos_suma, 200000);
generar_datos(datos_busca, 8000);
do {
printf("1) Suma lineal\n2) Buscar duplicado (cuadratico)\n3) Buscar duplicado optimizado\n0) Salir\n");
if (scanf("%d", &opcion) != 1) break;
switch (opcion) {
case 1:
printf("Tiempo: %.6f s\n", medir_segundos(suma_lineal, datos_suma, 200000));
break;
case 2:
printf("Tiempo: %.6f s\n", medir_segundos(busca_cuadratica_wrap, datos_busca, 8000));
break;
case 3:
printf("Tiempo: %.6f s\n", medir_segundos(busca_hash_wrap, datos_busca, 8000));
break;
case 0:
puts("Fin");
break;
default:
puts("Opcion invalida");
}
} while (opcion != 0);
return 0;
}