Liberar la memoria asignada para los nodos en la lista vinculada en C

Mehvish Ashiq 12 octubre 2023
Liberar la memoria asignada para los nodos en la lista vinculada en C

Hoy veremos cómo liberar o liberar la memoria asignada para los nodos en la lista enlazada en C.

Liberar la memoria asignada para los nodos en la lista vinculada en C

En este artículo, estamos utilizando la función free() para liberar la memoria que estaba reservada o asignada por la función malloc(). Significa que cada vez que llamamos a la función malloc(), debemos llamar a la función free() correspondiente en algún momento para liberar la memoria.

Al usar la lista enlazada en la programación C, a cada nodo de una lista enlazada se le asigna una memoria tan pronto como se llama a la función malloc(). Por lo tanto, liberamos la memoria asignada llamando al método free() siempre que el nodo o la lista enlazada completa ya no sean necesarios.

Supongamos que tenemos una lista enlazada que contiene los 3 nodos y decidimos que esta lista enlazada no es necesaria ahora. Podemos usar el ciclo para iterar sobre la lista enlazada y liberar la memoria asignada para cada nodo.

Recuerde, no podemos esperar que se libere toda la estructura de una lista enlazada llamando a la función free() desde el nodo raíz. Para entenderlo de manera práctica, estamos usando dos ejemplos de código.

  1. Imprima una lista enlazada completa y libere la memoria asignada para todos los nodos
  2. Imprima el nodo actual, guarde el puntero del siguiente nodo y libere la memoria para el nodo actual. Esto significa que estamos imprimiendo y liberando la memoria asignada en un ciclo.

Imprima toda la lista vinculada y libere la memoria asignada

Para aprender este escenario de manera práctica, definimos los nodos de la lista enlazada de la siguiente manera. Observe que definimos la estructura de forma recursiva, lo que permite la programación en C.

Además, estamos usando la estructura typedef en lugar de estructura solo para escribir un código más organizado y limpio. La diferencia entre estructura typedef y estructura se explica en detalle aquí.

typedef struct node {
  int data;
  struct node* next;
} nodes;

Rellene todos los nodos utilizando la función makeList(). Aquí, solo tenemos tres nodos en la lista enlazada.

struct node* makeList() {
  nodes* headNode = NULL;
  nodes* secondNode = NULL;
  nodes* thirdNode = NULL;

  headNode = malloc(sizeof(nodes));
  secondNode = malloc(sizeof(nodes));
  thirdNode = malloc(sizeof(nodes));

  headNode->data = 1;
  headNode->next = secondNode;

  secondNode->data = 2;
  secondNode->next = thirdNode;

  thirdNode->data = 3;
  thirdNode->next = NULL;

  return headNode;
}

El método printList() (abajo) itera sobre la lista enlazada e imprime cada nodo de la lista. Aquí, creamos el currentNode que hace referencia al headNode.

Luego, usamos un bucle while para verificar si el currentNode es NULL. De lo contrario, imprima los datos de currentNode y guarde la dirección del siguiente nodo en currentNode.

Este proceso continúa hasta que el currentNode es igual al NULL.

void printList(nodes* headNode) {
  nodes* currentNode = headNode;
  while (currentNode != NULL) {
    printf("The current element is %d\n", currentNode->data);
    currentNode = currentNode->next;
  }
}

Después de imprimir toda la lista enlazada, la función freeList() (a continuación) libera la memoria asignada para cada nodo.

La función freeList() comprueba si el headNode es NULL. Si es NULL, la lista está vacía, por lo que volvemos inmediatamente de esta función.

En segundo lugar, guarde el headNode en una variable currentNode y haga que el headNode apunte al siguiente nodo inmediato de nuestra lista. Lo estamos haciendo en headNode = headNode->next;.

En tercer lugar, liberamos de forma segura la memoria asignada utilizando free(currentNode). Ahora, el headNode apunta a la lista restante y vuelve al primer paso.

void freeList(nodes* headNode) {
  nodes* currentNode;
  while (headNode != NULL) {
    currentNode = headNode;
    headNode = headNode->next;
    free(currentNode);
  }
}

Finalmente, usamos el método main() para llamar a las funciones de la siguiente manera y lograr el objetivo.

int main() {
  nodes* headNode = makeList();
  printList(headNode);
  freeList(headNode);
  return 0;
}

Código de ejemplo completo

Todo el programa se ve como se muestra a continuación cuando ensamblamos todos los fragmentos de código.

#include <stdio.h>

typedef struct node {
  int data;
  struct node* next;
} nodes;

struct node* makeList() {
  nodes* headNode = NULL;
  nodes* secondNode = NULL;
  nodes* thirdNode = NULL;

  headNode = malloc(sizeof(nodes));
  secondNode = malloc(sizeof(nodes));
  thirdNode = malloc(sizeof(nodes));

  headNode->data = 1;
  headNode->next = secondNode;

  secondNode->data = 2;
  secondNode->next = thirdNode;

  thirdNode->data = 3;
  thirdNode->next = NULL;

  return headNode;
}

void printList(nodes* headNode) {
  nodes* currentNode = headNode;
  while (currentNode != NULL) {
    printf("The current element is %d\n", currentNode->data);
    currentNode = currentNode->next;
  }
}

void freeList(nodes* headNode) {
  nodes* currentNode;
  while (headNode != NULL) {
    currentNode = headNode;
    headNode = headNode->next;
    free(currentNode);
  }
}

int main() {
  nodes* headNode = makeList();
  printList(headNode);
  freeList(headNode);
  return 0;
}

Producción :

The current element is 1
The current element is 2
The current element is 3

Imprima el nodo actual, guarde el puntero para el siguiente nodo y libere la memoria asignada para el nodo actual

En este ejemplo de código, estamos imprimiendo el nodo actual, guardando la dirección para el siguiente nodo y liberando la memoria asignada para el nodo actual.

Todo es igual que en el ejemplo anterior excepto por dos cosas. Primero, no tenemos la función freeList() y segundo, tenemos printAndFreeList() en lugar de printList().

En la función printAndFreeList(), estamos iterando sobre la lista, imprimiendo el nodo actual, guardando el puntero para el resto de la lista enlazada y liberando la memoria para el nodo actual.

Este proceso continúa hasta que se encuentra el NULL.

void printAndFreeList(nodes* currentNode) {
  nodes* tempNode;
  while (currentNode != NULL) {
    tempNode = currentNode;
    printf("The current element is %d\n", currentNode->data);
    currentNode = currentNode->next;
    free(tempNode);
  }
}

Código de ejemplo completo

Todo el programa se ve de la siguiente manera.

#include <stdio.h>

typedef struct node {
  int data;
  struct node* next;
} nodes;

struct node* makeList() {
  nodes* headNode = NULL;
  nodes* secondNode = NULL;
  nodes* thirdNode = NULL;

  headNode = malloc(sizeof(nodes));
  secondNode = malloc(sizeof(nodes));
  thirdNode = malloc(sizeof(nodes));

  headNode->data = 1;
  headNode->next = secondNode;

  secondNode->data = 2;
  secondNode->next = thirdNode;

  thirdNode->data = 3;
  thirdNode->next = NULL;

  return headNode;
}

void printAndFreeList(nodes* currentNode) {
  nodes* tempNode;
  while (currentNode != NULL) {
    tempNode = currentNode;
    printf("The current element is %d\n", currentNode->data);
    currentNode = currentNode->next;
    free(tempNode);
  }
}

int main() {
  nodes* headNode = makeList();
  printAndFreeList(headNode);
  return 0;
}

Producción :

The current element is 1
The current element is 2
The current element is 3
Mehvish Ashiq avatar Mehvish Ashiq avatar

Mehvish Ashiq is a former Java Programmer and a Data Science enthusiast who leverages her expertise to help others to learn and grow by creating interesting, useful, and reader-friendly content in Computer Programming, Data Science, and Technology.

LinkedIn GitHub Facebook

Artículo relacionado - C Memory