Algoritmos y Estructura de Datos

Operaciones Insertar, Eliminar y Buscar en LDE


Para simplificar la programaci.ón, es conveniente agregar nodos especiales en los extremos de lista doblemente enlazada: un nodo header (cabeza) justo antes de la cabeza de la lista, y un nodo trailer (cola) justo despu.es de la cola de la lista. Estos nodos \falsos" o centinelas no guardan ningún elemento. La cabeza tiene una referencia sig válida pero una referencia prev nula, mientras cola tiene una referencia prev válida pero una referencia sig nula.

Insertar:

Partimos de una lista no vacía. Para simplificar, consideraremos que lista apunta al primer elemento de la lista doblemente enlazada:

El proceso es el siguiente:

  • nodo->siguiente debe apuntar a Lista.
  • nodo->anterior apuntará a Lista->anterior.
  • Lista->anterior debe apuntar a nodo.
  • Recuerda que Lista no tiene por qué apuntar a ningún miembro concreto de una lista doblemente enlazada, cualquier miembro es igualmente válido como referencia.

                        
    1. void Insertar(Lista *lista, int v) {
    2. pNodo nuevo, actual;
    3. /* Crear un nodo nuevo */
    4. nuevo = (pNodo)malloc(sizeof(tipoNodo));
    5. nuevo->valor = v;
    6. /* Colocamos actual en la primera posición de la lista */
    7. actual = *lista;
    8. if(actual) while(actual->anterior) actual = actual->anterior;
    9. /* Si la lista está vacía o el primer miembro es mayor que el nuevo */
    10. if(!actual || actual->valor > v) {
    11. /* Añadimos la lista a continuación del nuevo nodo */
    12. nuevo->siguiente = actual;
    13. nuevo->anterior = NULL;
    14. if(actual) actual->anterior = nuevo;
    15. if(!*lista) *lista = nuevo;
    16. }
    17. else {
    18. /* Avanzamos hasta el último elemento o hasta que el siguiente tenga
    19. un valor mayor que v */
    20. while(actual->siguiente && actual->siguiente->valor <= v)
    21. actual = actual->siguiente;
    22. /* Insertamos el nuevo nodo después del nodo anterior */
    23. nuevo->siguiente = actual->siguiente;
    24. actual->siguiente = nuevo;
    25. nuevo->anterior = actual;
    26. if(nuevo->siguiente) nuevo->siguiente->anterior = nuevo;
    27. }
    28. }
    Eliminar:

    Tenemos los dos casos posibles, que el nodo a borrar esté apuntado por Lista o que no. Si lo está, simplemente hacemos que Lista sea Lista->siguiente.

  • Si nodo apunta a Lista, hacemos que Lista apunte a Lista->siguiente.
  • Hacemos que nodo->siguiente->anterior apunte a NULL
  • Borramos el nodo apuntado por nodo.
  •                     
    1. void Borrar(Lista *lista, int v) {
    2. pNodo nodo;
    3. /* Buscar el nodo de valor v */
    4. nodo = *lista;
    5. while(nodo && nodo->valor < v) nodo = nodo->siguiente;
    6. while(nodo && nodo->valor > v) nodo = nodo->anterior;
    7. /* El valor v no está en la lista */
    8. if(!nodo || nodo->valor != v) return;
    9. /* Borrar el nodo */
    10. /* Si lista apunta al nodo que queremos borrar, apuntar a otro */
    11. if(nodo == *lista)
    12. if(nodo->anterior) *lista = nodo->anterior;
    13. else *lista = nodo->siguiente;
    14. if(nodo->anterior) /* no es el primer elemento */
    15. nodo->anterior->siguiente = nodo->siguiente;
    16. if(nodo->siguiente) /* no es el último nodo */
    17. nodo->siguiente->anterior = nodo->anterior;
    18. free(nodo);
    19. }

    Link de apoyo

  • Listas Doblemente Enlazadas
  • Listas Doblemente Enlazadas e implementación
  • ¿Cómo programar Listas Doblemente Enlazadas