Hoy vamos a ver un ejercicio de programación en lenguaje C, también conocido como ANSI C. Se trata de generar números aleatorios, agregarlos a una lista (arreglo) y luego agruparlos para obtener la frecuencia con la que se repiten.

El ejercicio dice así:

Realizar un programa que genere de manera aleatoria 100 números en el intervalo del conjunto del 1 al 20, y después genera una lista con la frecuencia de cada número. Los números generados de manera aleatoria se deben de visualizar; la frecuencia de números se debe visualizar.

Veamos cómo resolverlo usando una pila, arreglos y algunas funciones.

Algoritmo

Lo primero que debemos hacer es declarar un arreglo de 100 elementos, y llenarlo con números aleatorios. También declaramos una pila dinámica que nos servirá para registrar la frecuencia de los números.

Al llenar el arreglo también agregamos los elementos a la pila (de hecho el arreglo no haría falta, porque la pila tendrá tanto la frecuencia como el número).

En caso de que el número no exista en la pila, lo registramos con una frecuencia de 1. Y si el número ya existe, entonces aumentamos su frecuencia.

Trabajando con la lista

Declaramos un struct que será un nodo de la pila. Tiene el número, la frecuencia con la que aparece y un apuntador al siguiente nodo.

Obviamente esto se podría optimizar si usáramos un diccionario en lugar de una pila, pero a mi parecer es más fácil gestionarlo con una pila (a nivel de programación, no a nivel de rendimiento).

struct nodo {
    int numero;
    int frecuencia;
    struct nodo *siguiente;
};

struct nodo *superior = NULL;

Cuando se inserta un nuevo número por primera vez, se inserta un elemento en la pila.

void agregarPorPrimeraVez(int numero) {
    struct nodo *nuevoNodo = malloc(sizeof(struct nodo));
    nuevoNodo->numero = numero;
    nuevoNodo->frecuencia = 1;
    nuevoNodo->siguiente = superior;
    superior = nuevoNodo;
}

Como puedes ver en la línea 4, la frecuencia por defecto es 1.

Agregar número si ya existe

Hasta ahora tenemos nuestra pila y agregamos los números por primera vez, pero debemos manejar el caso de que el número ya exista justamente para aumentar su frecuencia en este ejercicio de programación en C.

Por lo tanto definimos una función que regresa un apuntador a la memoria en donde se encuentra el número, o NULL en caso de que no se encuentre. Queda así:

struct nodo *obtenerApuntadorANumero(int numeroBuscado) {
    struct nodo *temporal = superior;
    while (temporal != NULL) {
        if (temporal->numero == numeroBuscado) {
            return temporal;
        }
        temporal = temporal->siguiente;
    }
    return NULL;
}

Recorremos toda la pila y si encontramos el número, regresamos el apuntador a ese nodo. En caso contrario regresamos NULL.

Ahora cada que vayamos a agregar un número hacemos la comprobación: si ya existe, obtenemos el apuntador y aumentamos la frecuencia. Si no, lo agregamos por primera vez:

void registrarNumero(int numero) {
    struct nodo *apuntador = obtenerApuntadorANumero(numero);
    if (apuntador == NULL) {
        agregarPorPrimeraVez(numero);
    } else {
        apuntador->frecuencia++;
    }
}

Imprimir frecuencias

Ahora para imprimir los números aleatorios y la frecuencia con la que aparecen, simplemente recorremos la pila y vamos imprimiendo. Para ello usamos el ciclo while en el lenguaje C, así como printf.

void imprimirFrecuencias() {
    struct nodo *temporal = superior;
    while (temporal != NULL) {
        printf("Número %d frecuencia %d\n", temporal->numero, temporal->frecuencia);
        temporal = temporal->siguiente;
    }
}

Poniendo todo junto

Frecuencia de números en C usando pila – Programación

Anteriormente expliqué todo el código para contar la frecuencia con la que aparecen los números, pero no hemos visto el llenado del arreglo con números aleatorios ni las funciones para generar los números.

Todo el código queda como se ve a continuación dentro de main:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define MAXIMA_CANTIDAD 100
/*
  ____          _____               _ _           _       
 |  _ \        |  __ \             (_) |         | |      
 | |_) |_   _  | |__) |_ _ _ __ _____| |__  _   _| |_ ___ 
 |  _ <| | | | |  ___/ _` | '__|_  / | '_ \| | | | __/ _ \
 | |_) | |_| | | |  | (_| | |   / /| | |_) | |_| | ||  __/
 |____/ \__, | |_|   \__,_|_|  /___|_|_.__/ \__, |\__\___|
         __/ |                               __/ |        
        |___/                               |___/         
    
____________________________________
/ Si necesitas ayuda, contáctame en \
\ https://parzibyte.me               /
 ------------------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
Creado por Parzibyte (https://parzibyte.me). Este encabezado debe mantenerse intacto,
excepto si este es un proyecto de un estudiante.
*/
int aleatorio_en_rango(int minimo, int maximo) {
    return minimo + rand() / (RAND_MAX / (maximo - minimo + 1) + 1);
}

struct nodo {
    int numero;
    int frecuencia;
    struct nodo *siguiente;
};

struct nodo *superior = NULL;


struct nodo *obtenerApuntadorANumero(int numeroBuscado) {
    struct nodo *temporal = superior;
    while (temporal != NULL) {
        if (temporal->numero == numeroBuscado) {
            return temporal;
        }
        temporal = temporal->siguiente;
    }
    return NULL;
}

void agregarPorPrimeraVez(int numero) {
    struct nodo *nuevoNodo = malloc(sizeof(struct nodo));
    nuevoNodo->numero = numero;
    nuevoNodo->frecuencia = 1;
    nuevoNodo->siguiente = superior;
    superior = nuevoNodo;
}

void registrarNumero(int numero) {
    struct nodo *apuntador = obtenerApuntadorANumero(numero);
    if (apuntador == NULL) {
        agregarPorPrimeraVez(numero);
    } else {
        apuntador->frecuencia++;
    }
}

void imprimirFrecuencias() {
    struct nodo *temporal = superior;
    while (temporal != NULL) {
        printf("Número %d frecuencia %d\n", temporal->numero, temporal->frecuencia);
        temporal = temporal->siguiente;
    }
}


int main() {
    srand(getpid());
    int minimo = 1;
    int maximo = 20;
    int i;
    int numeros[MAXIMA_CANTIDAD];
    for (i = 0; i < MAXIMA_CANTIDAD; i++) {
        int numeroAleatorio = aleatorio_en_rango(minimo, maximo);
        numeros[i] = numeroAleatorio;
        registrarNumero(numeroAleatorio);
    }

    printf("Imprimiendo números\n");

    for (i = 0; i < MAXIMA_CANTIDAD; i++) {
        printf("%d,", numeros[i]);
    }
    printf("\n");
    printf("Imprimiendo frecuencias\n");
    imprimirFrecuencias();
    return 0;
}

Hay varias cosas en el método main, por ejemplo el llenado de la lista y la impresión de todas las cosas. Recuerda que en este caso hicimos conteo de números en C, anteriormente ya había explicado cómo contar la frecuencia de palabras.

También puedes leer más sobre lenguaje C en mi blog.

Igualmente dejo un vídeo en YouTube explicando todo este ejercicio

Estoy aquí para ayudarte 🤝💻


Estoy aquí para ayudarte en todo lo que necesites. Si requieres alguna modificación en lo presentado en este post, deseas asistencia con tu tarea, proyecto o precisas desarrollar un software a medida, no dudes en contactarme. Estoy comprometido a brindarte el apoyo necesario para que logres tus objetivos. Mi correo es parzibyte(arroba)gmail.com, estoy como@parzibyte en Telegram o en mi página de contacto

No te pierdas ninguno de mis posts 🚀🔔

Suscríbete a mi canal de Telegram para recibir una notificación cuando escriba un nuevo tutorial de programación.
parzibyte

Programador freelancer listo para trabajar contigo. Aplicaciones web, móviles y de escritorio. PHP, Java, Go, Python, JavaScript, Kotlin y más :) https://parzibyte.me/blog/software-creado-por-parzibyte/

Entradas recientes

Desplegar PWA creada con Vue 3, Vite y SQLite3 en Apache

Ya te enseñé cómo convertir una aplicación web de Vue 3 en una PWA. Al…

3 días hace

Arquitectura para wasm con Go, Vue 3, Pinia y Vite

En este artículo voy a documentar la arquitectura que yo utilizo al trabajar con WebAssembly…

3 días hace

Vue 3 y Vite: crear PWA (Progressive Web App)

En un artículo anterior te enseñé a crear un PWA. Al final, cualquier aplicación que…

3 días hace

Errores de Comlink y algunas soluciones

Al usar Comlink para trabajar con los workers usando JavaScript me han aparecido algunos errores…

3 días hace

Esperar promesa para inicializar Store de Pinia con Vue 3

En este artículo te voy a enseñar cómo usar un "top level await" esperando a…

3 días hace

Solución: Apache – Server unable to read htaccess file

Ayer estaba editando unos archivos que son servidos con el servidor Apache y al visitarlos…

4 días hace

Esta web usa cookies.