Las listas simplemente enlazadas tienen un gran inconveniente, que limita su utilización
extensiva: la lista no se puede recorrer en sentido inverso. Por esta razón se utilizan
generalmente las listas doblemente enlazadas.
Las listas doblemente enlazadas consisten en elementos que contienen datos y dos
enlaces, uno al siguiente elemento y el otro al elemento procedente. Una lista que tiene
dos enlaces en lugar de uno solo, tiene dos grandes ventajas:
1.- La lista se puede se leer en cualquier dirección, esto no solo simplifica la ordenación
de la lista, si no también, en el caso de una base de datos, permite a un usuario explorar
la lista en cualquier dirección.
2.- Ya sea que con el enlace hacia delante o con el enlace hacia atrás se puede leer la
lista completa, si un enlace se pierde o no es válido, la lista se puede reconstruir usando
el otro enlace. Esto tiene sentido solo en caso de una falla de equipo.
Construir una lista doblemente enlazada es similar a construir una lista simplemente
enlazada, excepto que la estructura tiene que tener un sitio para albergar enlaces.
Hay tres casos a considerar cuando se borra un elemento de una lista doblemente
enlazada:
En las siguientes figuras se muestra como se reordena los enlaces para cada caso:
1. índice = primero
2. primero = primero -> sig
3. índice sig= null
4. principio ant= null
1. índice = primero
2. buscar en índice sig el elemento a borrar
3. copiar borrado = índice sig
4. indice sig = borrado sig
5. borrado sig ant= índice
6. borrado sig= null,
7. borrado ant=null
8. delete (borrado)
1. Índice = ultimo
2. último = ultimo ant
3. índice ant = null
4. ultimo sig = null
PROGRAMA #17
Programa que sirve para crear y manejar una lista doblemente enlazada de números
enteros.
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <iostream>
class dato
{
int x;
struct dato *sig;
struct dato *ant;
public:
dato *primero, *nuevo, *indice, *ultimo;
void asigna_memoria(void);
void intro_dato(void);
void lista_datos1(void);
void lista_datos2(void);
dato *busca_dato(void);
void borra_dato(void);
};
void dato::asigna_memoria(void)
{
nuevo= new (class dato);
if(nuevo == NULL)
cout <<"\n No hay espacio de memoria";
else
cout <<"\n Se asigna espacio de memoria para el nuevo elemento";
}
void dato::intro_dato(void)
{
asigna_memoria();
if(nuevo == NULL) return;
if( primero == NULL)
{
primero = indice = ultimo = nuevo;
nuevo->sig = NULL;
nuevo->ant = NULL;
}
else
{ indice = primero;
while(indice ->sig != NULL)
indice = indice ->sig;
indice->sig = nuevo;
nuevo->sig = NULL;
nuevo->ant = indice;
indice = ultimo = nuevo;
}
cout <<"\n Dame el dato (entero):";
cin >> indice->x;
}
void dato::lista_datos1(void)
{
cout <<"\n LISTA LOS DATOS DEL PRINCIPIO AL FINAL ";
if(primero == NULL)
{cout <<"\n LISTA VACIA "; return; }
indice = primero;
do {
cout <<"\nDATO= "<<indice ->x;
indice = indice->sig;
} while (indice != NULL); cout << "\n";
}
void dato::lista_datos2(void)
{
cout <<"\n LISTA LOS DATOS DEL FINAL AL PRINCIPIO";
if(primero == NULL || ultimo == NULL)
{cout <<"\n LISTA VACIA "; return; }
indice = ultimo;
do {
cout <<"\nDATO= "<<indice ->x;
indice = indice->ant;
} while (indice != NULL); cout << "\n";
}
dato *dato::busca_dato(void)
{
int xdato;
cout <<"\n BUSQUEDA DE UN DATO ";
cout <<"\n Dato a buscar : ";
cin >>xdato;
if(primero == NULL)
{cout <<"\n LISTA VACIA "; return(NULL); }
indice = primero;
do {
if(xdato == indice->x)
{ cout <<"\n Si esta el dato "<<indice->x << " en la lista";
return(indice);
}
indice = indice->sig;
}while (indice != NULL);
cout <<"\n NO SE encontro el dato "<< xdato << " en la lista";
return(NULL);
}
void dato::borra_dato(void)
{
dato *y;
cout <<"\n BUSQUEDA DEL DATO A BORRAR ";
y = busca_dato();
if(y == NULL) return;
cout <<"\n Se encontro el dato a borrar : "<< y->x << " y se procede a borrar\n";
indice = y;
if(y == primero)
{
primero = primero->sig; y->sig = NULL;
if(primero != NULL) primero->ant = NULL;
delete(y);
return;}
if(y == ultimo)
{
ultimo = ultimo->ant; y->ant = NULL;
if( ultimo != NULL) ultimo->sig = NULL;
delete(y);
return;}
indice=primero;
while(indice ->sig != y)
indice = indice->sig;
indice -> sig = y->sig;
y->sig->ant = indice;
delete (y);
}
main(void)
{
dato lista;
int opcion;
lista.primero=NULL;
lista.nuevo=NULL;
lista.indice=NULL;
lista.ultimo=NULL;
for(;;)
{
cout <<"\n MANEJO DE UNA LISTA DOBLEMENTE ENLAZADA";
cout <<"\n 1. Introducir un dato a lista";
cout <<"\n 2. Listar la lista del principio al final";
cout <<"\n 3. Listar la lista del final al principio";
cout <<"\n 4. Busqueda de un dato";
cout <<"\n 5. Borrado de un dato";
cout <<"\n 6. Salir";
cout <<"\n opcion : ";
cin >>opcion;
switch(opcion)
{ case 1: lista.intro_dato();
break;
case 2: lista.lista_datos1();
break;
case 3: lista.lista_datos2();
break;
case 4: lista.busca_dato();
break;
case 5: lista.borra_dato();
break;
case 6: cout << "\nFIN";
getch();
exit(0);
}
}
}