Lista doblemente enlazada , la enciclopedia libre

En ciencias de la computación, una lista doblemente enlazada es una estructura de datos que consiste en un conjunto de nodos enlazados secuencialmente. Cada nodo contiene tres campos, dos para los llamados enlaces, que son referencias al nodo siguiente y al anterior en la secuencia de nodos, y otro más para el almacenamiento de la información (en este caso un entero). El enlace al nodo anterior del primer nodo y el enlace al nodo siguiente del último nodo, apuntan a un tipo de nodo que marca el final de la lista, normalmente un nodo centinela o puntero null, para facilitar el recorrido de la lista. Si existe un único nodo centinela, entonces la lista es circular a través del nodo centinela.

Una lista doblemente enlazada cuyos nodos contienen tres campos: un valor entero, el enlace al nodo siguiente, y el enlace al nodo anterior.
Una lista doblemente enlazada cuyos nodos contienen tres campos: un valor entero, el enlace al nodo siguiente, y el enlace al nodo anterior.

El doble enlace de los nodos permite recorrer la lista en cualquier dirección. Mientras que agregar o eliminar un nodo en una lista doblemente enlazada requiere cambiar más enlaces que en estas mismas operaciones en una lista enlazada simple, las operaciones son más simples porque no hay necesidad de mantener guardado el nodo anterior durante el recorrido, ni necesidad de recorrer la lista para hallar el nodo anterior, la referencia al nodo que se quiere eliminar o insertar es lo único necesario.

Nomenclatura e implementación

[editar]

El primer y el último nodo de una lista doblemente enlazada son accesibles inmediatamente (o sea, accesibles sin necesidad de recorrer la lista, y usualmente llamados cabeza y cola) y esto permite recorrerla desde el inicio o el final de la lista, respectivamente. Cualquier nodo de la lista doblemente enlazada, una vez obtenido, puede ser usado para empezar un nuevo recorrido de la lista, en cualquier dirección (hacia el principio o el final), desde el nodo dado.

Los enlaces de un nodo de una lista doblemente enlazada son frecuentemente llamados anterior y siguiente o antecesor y sucesor. Las referencias guardadas en los enlaces son usualmente implementadas como punteros,pero también podrían ser índices de un array donde están los nodos.

Algoritmos Básicos

[editar]

Lista doblemente enlazada

[editar]
record NodoDoblementeEnlazado {     siguiente // Una referencia al nodo siguiente     anterior // Una referencia al nodo anterior     dato // dato o referencia al dato   } 
record ListaDoblementeEnlazada {      NodoDoblementeEnlazado primerNodo   // referencia al primer nodo de la lista      NodoDoblementeEnlazado ultimoNodo    // referencia al último nodo de la lista } 

Recorriendo la lista

[editar]

Recorrer una lista doblemente enlazada puede ser en cualquier dirección. De hecho, la dirección del recorrido puede cambiar muchas veces, si se desea. Recorrido es frecuentemente llamado iteración.

Hacia adelante

nodo  := lista.primerNodo  while nodo ≠ null      <Hacer algo con nodo.dato>      nodo  := nodo.siguiente  

Hacia atrás

nodo  := lista.ultimoNodo      while nodo ≠ null      <Hacer algo con nodo.dato>      nodo  := nodo.anterior  

Insertando un nodo

[editar]

Estas funciones insertan un nodo ya sea adelante o atrás de un nodo dado:

function InsertaAtras(Lista lista, Nodo nodo, Nodo nuevoNodo)      nuevoNodo.anterior  := nodo      nuevoNodo.siguiente  := nodo.siguiente        if nodo.siguiente  == null          lista.ultimoNodo  := nuevoNodo      else          nodo.siguiente.anterior := nuevoNodo      nodo.siguiente  := nuevoNodo 
function InsertaAdelante(Lista lista, Nodo nodo, Nodo nuevoNodo)      nuevoNodo.anterior  := nodo.anterior        nuevoNodo.siguiente  := nodo      if nodo.anterior  == null          lista.primerNodo  := nuevoNodo      else          nodo.anterior.siguiente  := nuevoNodo      nodo.anterior  := nuevoNodo 

También necesitamos una función para insertar un nodo al principio de una lista posiblemente vacía:

function InsertaAlPrincipio(Lista lista, Nodo nuevoNodo)      if lista.primerNodo == null          lista.primerNodo := nuevoNodo          lista.ultimoNodo   := nuevoNodo          nuevoNodo.anterior  := null          nuevoNodo.siguiente  := null      else          InsertaAtras(lista, lista.primerNodo , nuevoNodo) 

La siguiente función inserta al final:

function InsertaAlFinal(Lista lista, Nodo nuevoNodo)      if lista.ultimoNodo == null          InsertaAlPrincipio(lista, nuevoNodo)      else          InsertatAdelante(lista, lista.ultimoNodo, nuevoNodo) 

Borrando un Nodo

[editar]

Eliminar un nodo es más fácil que insertar, pero requiere un manejo especial si el nodo a eliminar es el primerNodo o el ultimoNodo:

function Elimina(Lista lista, Nodo nodo)    if nodo.anterior == null        lista.primerNodo  := nodo.siguiente    else        nodo.anterior.siguiente := nodo.siguiente    if nodo.siguiente== null        lista.ultimoNodo  := nodo.anterior    else        nodo.siguiente.anterior := nodo.anterior    destroy nodo 

Una sutil consecuencia del procedimiento de arriba es que eliminando el último nodo de una lista asigna a primerNodo y a ultimoNodo a null, y de esta forma maneja correctamente eliminar el último nodo de una lista de un solo elemento. Tampoco necesitamos separar los métodos "EliminarAtras" o "EliminarAdelante", porque en una lista doblemente enlazada podemos usar "Elimina(nodo.anterior)" o "Elimina(nodo.siguiente)" cuando sea válido. También se asume que está garantizado que el nodo siendo eliminado existe. Si el nodo no existe en la lista, entonces algún manejo de error será requerido.

Lista Doblemente Enlazada Circular

[editar]

Recorriendo la lista

[editar]

Asumir que algunNodo es algún nodo en una lista no vacía, este código recorre la lista empezando por' 'algunNodo:

Hacia adelante

nodo  := algunNodo  do      <Hacer algo con nodo.dato>      nodo  := nodo.siguiente  while nodo ≠ algunNodo 

Hacia atrás

nodo  := algunNodo  do      <Hacer algo con nodo.dato>      nodo  := nodo.anterior  while nodo ≠ algunNodo 

Notar que la condición se ejecuta al final del ciclo. Esto es importante para el caso en que la lista contiene el único nodo algunNodo.

Insertar un Nodo

[editar]

Esta simple función inserta un nodo en una lista doblemente enlazada circular delante de un elemento dado:

function InsertaDelante(Nodo nodo, Nodo nuevoNodo)      nuevoNodo.siguiente  := nodo.siguiente        nuevoNodo.anterior  := nodo      nodo.siguiente.anterior  := nuevoNodo      nodo.siguiente       := nuevoNodo 

Para hacer un "InsertaAtras" podemos hacer simplemente "InsertaDelante(nodo.anterior, nuevoNodo)".

Insertar un elemento en una lista posiblemente vacía requiere una función especial:

function InsertaAlFinal(Lista lista, Nodo nodo)      if lista.ultimoNodo == null          nodo.anterior := nodo          nodo.siguiente := nodo      else          InsertaDelante(lista.ultimoNodo, nodo)      lista.ultimoNodo:= nodo 

Para insertar en el principio simplemente hacemos "InsertaDelante(lista.ultimoNodo , nodo)".

Finalmente para eliminar un nodo debemos lidiar con el caso donde la lista es vacía:

function Elimina(Lista lista, Nodo nodo)      if nodo.siguiente == nodo          lista.ultimoNodo := null      else          nodo.siguiente.anterior := nodo.anterior          nodo.anterior.siguiente := nodo.siguiente          if nodo == lista.ultimoNodo              lista.ultimoNodo:= nodo.anterior;      destroy nodo 


Implementaciones en Java

[editar]

Lista doblemente enlazada

[editar]
class NodoDoble{     int informacion;     NodoDoble siguiente, anterior;          public NodoDoble(int info){         informacion=info;         siguiente=null;         anterior=null;     } }  public class ListaDoblementeEnlazada{     NodoDoble inicio, fin;          public ListaDoblementeEnlazada(){         inicio=fin=null;     }          boolean estaVacia(){         if(inicio == null && fin == null)             return true;         return false;     }          void insertarEnfrente(int dato){         NodoDoble nodito=new NodoDoble(dato);         if(estaVacia()==true){             inicio=nodito;             fin=nodito;         }         else{             nodito.siguiente=inicio;             inicio.anterior=nodito;         }         inicio=nodito;     }          void insertarAtras(int dato){         NodoDoble nodito=new NodoDoble(dato);         if(estaVacia()==true){             inicio=nodito;             fin=nodito;         }         else{             fin.siguiente=nodito;             nodito.anterior=fin;         }         fin=nodito;     }          void eliminarEnfrente(){         if(estaVacia()==true){             System.out.println("Lista vacía, no se puede eliminar");         }         else if(inicio == fin){             inicio=null;             fin=null;         }         else{             NodoDoble auxiliar=inicio;             System.out.println("El dato que fue eliminado es: "+inicio.informacion);             inicio=inicio.siguiente;             auxiliar.anterior=null;             auxiliar.siguiente=null;             inicio.anterior=null;         }     }          void eliminarAtras(){         if(estaVacia() == true){             System.out.println("Lista vacía, no se puede eliminar");         }         else if(inicio == fin){             inicio=null;             fin=null;         }         else{             NodoDoble auxiliar=fin;             System.out.println("El dato que fue eliminado es: "+fin.informacion);             fin=fin.anterior;             fin.siguiente=null;             auxiliar.anterior=null;             auxiliar.siguiente=null;         }     }          void imprimirListaIzqDer(){//Impresion de inicio a fin         if(estaVacia() == true){             System.out.println("Lista vacía");         }         else if(inicio == fin){            System.out.println(inicio.informacion);         }         else{             NodoDoble auxiliar=inicio;             while(auxiliar != null){                 System.out.println(auxiliar.informacion+" ");                 auxiliar=auxiliar.siguiente;             }         }     }          void imprimirListaDerIzq(){//Impresion de fin a inicio         if(estaVacia() == true){             System.out.println("Lista vacía");         }         else if(inicio == fin){            System.out.println(inicio.informacion);         }         else{             NodoDoble auxiliar=fin;             while(auxiliar != null){                 System.out.println(auxiliar.informacion+" ");                 auxiliar=auxiliar.anterior;             }         }     }          public static void main(String arrr[]){         ListaDoblementeEnlazada listita = new ListaDoblementeEnlazada();         listita.insertarEnfrente(19);         listita.insertarAtras(28);         listita.insertarEnfrente(11);         listita.insertarAtras(51);         listita.eliminarEnfrente();         listita.imprimirListaIzqDer();         listita.insertarAtras(9);         listita.imprimirListaIzqDer();         listita.eliminarAtras();         listita.imprimirListaDerIzq();     } } 

Lista doblemente enlazada circular

[editar]
class NodoDoble{     int informacion;     NodoDoble siguiente, anterior;          public NodoDoble(int info){         informacion=info;         siguiente=null;         anterior=null;     } }  class ListaDoblementeEnlazadaCircular{     NodoDoble inicio;          public ListaDoblementeEnlazadaCircular(){         inicio=null;     }          void estaVacia(){         if(inicio == null)             return true;         return false;     }          void insertarEnfrente(int dato){         NodoDoble nodito=new NodoDoble(dato);         if(estaVacia()==true){             inicio=nodito;             inicio.siguiente=inicio;             inicio.anterior=inicio;         }         else{             nodito.siguiente=inicio;             inicio.anterior.siguiente=nodito;             nodito.anterior=inicio.anterior;             inicio.anterior=nodito;         }         inicio=nodito;     }          void insertarAtras(int dato){         NodoDoble nodito=new NodoDoble(dato);         if(estaVacia()==true){             inicio=nodito;             inicio.siguiente=inicio;             inicio.anterior=inicio;         }         else{             nodito.siguiente=inicio;             inicio.anterior.siguiente=nodito;             nodito.anterior=inicio.anterior;             inicio.anterior=nodito;         }     }          void eliminarEnfrente(){         if(estaVacia()==true){             System.out.println("Lista vacía, no se puede eliminar");         }         else if(inicio == inicio.siguiente){             inicio=null;         }         else{             NodoDoble auxiliar=inicio;             System.out.println("El dato que fue eliminado es: "+inicio.informacion);             inicio=inicio.siguiente;             auxiliar.anterior.siguiente=inicio;             inicio.anterior=auxiliar.anterior;             auxiliar.anterior=null;             auxiliar.siguiente=null;         }     }          void eliminarAtras(){         if(estaVacia() == true){             System.out.println("Lista vacía, no se puede eliminar");         }         else if(inicio == inicio.siguiente){             inicio=null;         }         else{             NodoDoble auxiliar=inicio.anterior;             System.out.println("El dato que fue eliminado es: "+fin.informacion);             auxiliar.anterior.siguiente=inicio;             inicio.anterior=auxiliar.anterior;             auxiliar.anterior=null;             auxiliar.siguiente=null;         }     }          void imprimirListaIzqDer(){//Impresion de inicio a fin         if(estaVacia() == true){             System.out.println("Lista vacía");         }         else if(inicio == inicio.siguiente){            System.out.println(inicio.informacion);         }         else{             NodoDoble auxiliar=inicio;             do{                 System.out.println(auxiliar.informacion+" ");                 auxiliar=auxiliar.siguiente;             }while(auxiliar != inicio);         }     }          void imprimirListaDerIzq(){//Impresion de fin a inicio         if(estaVacia() == true){             System.out.println("Lista vacía");         }         else if(inicio == inicio.siguiente){            System.out.println(inicio.informacion);         }         else{             NodoDoble auxiliar=inicio.previo;             do{                 System.out.println(auxiliar.informacion+" ");                 auxiliar=auxiliar.previo;             }while(auxiliar != inicio.previo);         }     }          public static void main(String arrr[]){         ListaDoblementeEnlazadaCircular listita = new ListaDoblementeEnlazadaCircular();         listita.insertarEnfrente(19);         listita.insertarAtras(28);         listita.insertarEnfrente(11);         listita.insertarAtras(51);         listita.insertarAtras(9);         listita.imprimirListaIzqDer();         listita.eliminarAtras();         listita.imprimirListaDerIzq();     } } 


Véase también

[editar]

Lista (informática)