Algoritmos y Estructura de Datos

Listas circulares y operaciones


Una lista circular es un tipo de estructura de datos en la que cada elemento tiene un enlace a otro elemento en la lista, formando una estructura circular. Esto significa que la lista no tiene un comienzo o un final definidos, sino que cada elemento de la lista se encuentra en una posición relativa a los demás elementos.

Una de las principales ventajas de las listas circulares es que permiten un acceso rápido a cualquier elemento de la lista, ya que no es necesario recorrer la lista desde el principio para llegar a un elemento específico. Además, las listas circulares también pueden ser útiles en situaciones en las que se desea implementar una estructura de datos que permita el recorrido continuo de los elementos, como en el caso de una lista de reproducción de música o una lista de imágenes en una presentación.

Otra ventaja de las listas circulares es que pueden ser implementadas de manera eficiente utilizando punteros, lo que permite un acceso rápido a cualquier elemento de la lista y una inserción y eliminación rápidas de elementos. Sin embargo, también es importante tener en cuenta que las listas circulares requieren más espacio de memoria que otras estructuras de datos, ya que cada elemento debe almacenar un enlace adicional a otro elemento de la lista.

Insertar:

Para insertar un elemento en una lista circular, necesitarás seguir los siguientes pasos:

  • Crea un nuevo nodo para almacenar el elemento que deseas insertar. Este nodo debe tener un campo para el valor del elemento y otro para el enlace al siguiente elemento de la lista.
  • Si la lista está vacía, debes establecer el enlace del nodo recién creado al mismo nodo, de manera que forme una lista circular con un solo elemento.
  • Si la lista ya tiene elementos, debes encontrar el lugar donde deseas insertar el nuevo elemento. Puedes hacer esto recorriendo la lista hasta encontrar el elemento anterior al que deseas insertar o utilizando un puntero para saltar directamente al lugar correcto.
  • Una vez que hayas encontrado el lugar correcto, debes establecer el enlace del nodo anterior al nuevo nodo y el enlace del nuevo nodo al siguiente nodo en la lista. De esta manera, el nuevo nodo queda insertado en la lista circular en la posición correcta.
  • Es importante tener en cuenta que, al tratarse de una lista circular, el último elemento de la lista debe tener un enlace al primer elemento de la lista. De esta manera, la lista circular queda cerrada y permite el recorrido continuo de sus elementos.

                        
    1. class ListaCircular {
    2. private:
    3. struct Nodo {
    4. int valor;
    5. Nodo* siguiente;
    6. };
    7. Nodo* cabeza;
    8. public:
    9. ListaCircular() : cabeza(nullptr) {}
    10. void Insertar(int valor) {
    11. // Crea un nuevo nodo para almacenar el valor
    12. Nodo* nuevo = new Nodo;
    13. nuevo->valor = valor;
    14. if (cabeza == nullptr) {
    15. // Si la lista está vacía, el nuevo nodo es la cabeza y tiene enlace a sí mismo
    16. cabeza = nuevo;
    17. cabeza->siguiente = cabeza;
    18. } else {
    19. // Si la lista ya tiene elementos, encuentra el último nodo y enlázalo con el nuevo nodo
    20. Nodo* ultimo = cabeza;
    21. while (ultimo->siguiente != cabeza) {
    22. ultimo = ultimo->siguiente;
    23. }
    24. ultimo->siguiente = nuevo;
    25. nuevo->siguiente = cabeza;
    26. }
    27. }
    28. };
    Eliminar

    Para eliminar un elemento de una lista circular, debes seguir los siguientes pasos:

  • Encuentra el nodo que almacena el elemento que deseas eliminar. Puedes hacer esto recorriendo la lista hasta encontrar el elemento o utilizando un puntero para saltar directamente al lugar correcto.
  • Una vez que has encontrado el nodo que almacena el elemento a eliminar, debes eliminar el enlace al siguiente nodo de la lista. Para ello, debes establecer el enlace del nodo anterior al siguiente nodo en la lista, saltándose el nodo que deseas eliminar.
  • Finalmente, debes eliminar el nodo que almacena el elemento a eliminar. Esto puede hacerse utilizando la función delete de C++ o la función free de C.
  • Es importante tener en cuenta que, al tratarse de una lista circular, debes asegurarte de que el último elemento de la lista tenga un enlace al primer elemento de la lista después de eliminar el elemento. De esta manera, la lista circular queda cerrada y permite el recorrido continuo de sus elementos.

                        
    1. class ListaCircular {
    2. private:
    3. struct Nodo {
    4. int valor;
    5. Nodo* siguiente;
    6. };
    7. Nodo* cabeza;
    8. public:
    9. ListaCircular() : cabeza(nullptr) {}
    10. void Eliminar(int valor) {
    11. // Si la lista está vacía, no hay nada que eliminar
    12. if (cabeza == nullptr) {
    13. return;
    14. }
    15. // Si el elemento a eliminar es el único de la lista, elimina la cabeza
    16. if (cabeza->siguiente == cabeza && cabeza->valor == valor) {
    17. delete cabeza;
    18. cabeza = nullptr;
    19. return;
    20. }
    21. // Si el elemento a eliminar es la cabeza, encuentra el último nodo y cambia la cabeza
    22. if (cabeza->valor == valor) {
    23. Nodo* ultimo = cabeza;
    24. while (ultimo->siguiente != cabeza) {
    25. ultimo = ultimo->siguiente;
    26. }
    27. cabeza = cabeza->siguiente;
    28. ultimo->siguiente = cabeza;
    29. delete ultimo;
    30. return;
    31. }
    32. // Si el elemento a eliminar está en otra parte de la lista, busca su nodo anterior y enlázalo con el siguiente
    33. Nodo* anterior = cabeza;
    34. while (anterior->siguiente != cabeza && anterior->siguiente->valor != valor) {
    35. anterior = anterior->siguiente;
    36. }
    37. // Si se encontró el elemento a eliminar, elimina su nodo y enlaza el anterior con el siguiente
    38. if (anterior->siguiente != cabeza) {
    39. Nodo* eliminar = anterior->siguiente;
    40. anterior->siguiente = eliminar->siguiente;
    41. delete eliminar;
    42. }
    43. }
    44. };
    Buscar:

    Para buscar un elemento en una lista circular, puedes seguir los siguientes pasos:

  • Comienza en el primer elemento de la lista y recorre la lista hasta encontrar el elemento que deseas buscar o hasta llegar al final de la lista.
  • Mientras recorres la lista, comparas el valor de cada elemento con el valor que estás buscando. Si encuentras un elemento con el valor correcto, puedes devolver el elemento o la posición en la que se encuentra.
  • Si llegas al final de la lista y no has encontrado el elemento que estás buscando, debes volver al principio de la lista y continuar recorriendo hasta encontrar el elemento o hasta llegar de nuevo al final de la lista.
  • Es importante tener en cuenta que, al tratarse de una lista circular, debes asegurarte de que no entras en un bucle infinito mientras recorres la lista. Una forma de evitar esto es utilizar una variable para llevar la cuenta del número de elementos que has recorrido y detener la búsqueda cuando hayas recorrido todos los elementos de la lista.

                        
    1. class ListaCircular {
    2. private:
    3. struct Nodo {
    4. int valor;
    5. Nodo* siguiente;
    6. };
    7. Nodo* cabeza;
    8. public:
    9. ListaCircular() : cabeza(nullptr) {}
    10. int Buscar(int valor) {
    11. // Si la lista está vacía, devuelve -1
    12. if (cabeza == nullptr) {
    13. return -1;
    14. }
    15. // Recorre la lista hasta encontrar el elemento o llegar al final de la lista
    16. Nodo* actual = cabeza;
    17. int posicion = 0;
    18. while (actual->siguiente != cabeza && actual->valor != valor) {
    19. actual = actual->siguiente;
    20. posicion++;
    21. }
    22. // Si se encontró el elemento, devuelve su posición
    23. if (actual->valor == valor) {
    24. return posicion;
    25. }
    26. // Si no se encontró el elemento, devuelve -1
    27. return -1;
    28. }
    29. };

    Link de apoyo

  • Listas Circulares
  • Listas Circulares en C++, Java y Python