You are on page 1of 9

ESTRUCTURA DE DATOS AVANZADOS

LISTAS DOBLES

LISTAS DOBLEMENTE ENLAZADAS


DEFINICIN
Una lista doblemente enlazada es una lista lineal en la que cada nodo tiene dos
enlaces, uno al nodo siguiente, y otro al anterior.
Las listas doblemente enlazadas no necesitan un nodo especial para acceder a ellas,
pueden recorrerse en ambos sentidos a partir de cualquier nodo, esto es porque a
partir de cualquier nodo, siempre es posible alcanzar cualquier nodo de la lista,
hasta que se llega a uno de los extremos.
Declaraciones de tipos para manejar listas doblemente enlazadas en C
Para C, y basndonos en la declaracin de nodo que hemos visto, trabajaremos con
los siguientes tipos:
typedef struct _nodo {
int dato;
struct _nodo *siguiente;
struct _nodo *anterior;
} tipoNodo;
typedef tipoNodo *pNodo;
typedef tipoNodo *Lista;
tipoNodo es el tipo para declarar nodos, evidentemente.
pNodo es el tipo para declarar punteros a un nodo.
Lista es el tipo para declarar listas abiertas doblemente enlazadas. Tambin es
posible, y potencialmente til, crear listas doblemente enlazadas y circulares.

OPERACIONES BSICAS CON LISTAS DOBLEMENTE ENLAZADAS


1. Aadir un elemento
Aadir elemento en una lista doblemente enlazada vaca:
Partiremos de que ya tenemos el nodo a insertar y, por supuesto un puntero que
apunte a l, adems el puntero que define la lista, que valdr NULL:

ESTRUCTURA DE DATOS AVANZADOS

LISTAS DOBLES

El proceso es muy simple, bastar con que:


1. lista apunta a nodo.
2. lista->siguiente y lista->anterior apunten a null.

Insertar un elemento en la primera posicin de la lista:


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

El proceso es el siguiente:
1. nodo->siguiente debe apuntar a Lista.
2. nodo->anterior apuntar a Lista->anterior.
3. Lista->anterior debe apuntar a nodo.

Recuerda que Lista no tiene por qu apuntar a ningn miembro concreto de una
lista doblemente enlazada, cualquier miembro es igualmente vlido como
referencia.
2. Insertar un elemento en la ltima posicin de la lista:
Igual que en el caso anterior, partiremos de una lista no vaca, y de nuevo para
simplificar, que Lista est apuntando al ltimo elemento de la lista:

ESTRUCTURA DE DATOS AVANZADOS

LISTAS DOBLES

El proceso es el siguiente:
1. nodo->siguiente debe apuntar a Lista->siguiente (NULL).
2. Lista->siguiente debe apuntar a nodo.
3. nodo->anterior apuntar a Lista.

3. Buscar o localizar un elemento de una lista doblemente enlazada


Para recorrer una lista procederemos de un modo parecido al que usbamos con las
listas abiertas, ahora no necesitamos un puntero auxiliar, pero tenemos que tener
en cuenta que Lista no tiene por qu estar en uno de los extremos:
1. Retrocedemos hasta el comienzo de la lista, asignamos a lista el valor de
lista->anterior mientras lista->anterior no sea NULL.
2. Abriremos un bucle que al menos debe tener una condicin, que el ndice no
sea NULL.
3. Dentro del bucle asignaremos a lista el valor del nodo siguiente al actual.
ELIMINAR UN ELEMENTO DE UNA LISTA DOBLEMENTE ENLAZADA:
Eliminar el nico nodo en una lista doblemente enlazada:
En este caso, ese nodo ser el apuntado por Lista.

1. Eliminamos el nodo.
2. Hacemos que Lista apunte a NULL.

ESTRUCTURA DE DATOS AVANZADOS

LISTAS DOBLES

Eliminar el primer nodo de una lista doblemente enlazada:


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.

1. Si nodo apunta a Lista, hacemos que Lista apunte a Lista->siguiente.


2. Hacemos que nodo->siguiente->anterior apunte a NULL
3. Borramos el nodo apuntado por nodo.

El paso 2 depara el nodo a borrar del resto de la lista, independientemente del nodo
al que apunte Lista.
Eliminar el ltimo nodo de una lista doblemente enlazada:
De nuevo 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->anterior.

1. Si nodo apunta a Lista, hacemos que Lista apunte a Lista->anterior.


2. Hacemos que nodo->anterior->siguiente apunte a NULL
3. Borramos el nodo apuntado por nodo.

El paso 2 depara el nodo a borrar del resto de la lista, independientemente del nodo
al que apunte Lista.

ESTRUCTURA DE DATOS AVANZADOS

LISTAS DOBLES

Eliminar un nodo intermedio de una lista doblemente enlazada:


De nuevo 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->anterior o
Lista->siguiente
Se trata de un caso ms general de los dos casos anteriores..

1. Si nodo apunta a Lista, hacemos que Lista apunte a Lista->anterior (o Lista>siguiente).


2. Hacemos que nodo->anterior->siguiente apunte a nodo->siguiente.
3. Hacemos que nodo->siguiente->anterior apunte a nodo->anterior.
4. Borramos el nodo apuntado por nodo.

EJEMPLO
PROGRAMA QUE REALICE TODAS LAS OPERACIONES BASICAS EN UNA LISTA
DOBLEMENTE ENLAZADA
#include<conio.h>
#include<iostream.h>
struct nodo
{
int nro;
struct nodo* sgte;
struct nodo* ante;
};
typedef struct nodo* Tlista;
void InsertaAlInicio(Tlista&,int);
void InsertaAlFinal(Tlista&,int);
void EliminaAlInicio(Tlista&);
bool Busqueda(Tlista,int,int&);
void EliminarLista(Tlista&);
void Imprimir(Tlista);
void EliminaElemento(Tlista&,int);
void Ordenar(Tlista&);
void main(void)

ESTRUCTURA DE DATOS AVANZADOS

LISTAS DOBLES

{
Tlista lista=NULL;
int opc,valor,pos;
bool R;
do
{
cout<<"======================================\n";
cout<<"=============== MENU =================\n";
cout<<"======================================\n";
cout<<"| 1.- Inserta al inicio
|\n";
cout<<"| 2.- Inserta al final
|\n";
cout<<"| 3.- Busqueda
|\n";
cout<<"| 4.- Eliminar Lista
|\n";
cout<<"| 5.- Listado [Izquierda - Derecha] |\n";
cout<<"| 6.- Elimina al inicio
|\n";
cout<<"| 7.- Elimina Elemento
|\n";
cout<<"| 8.- Ordenar Lista
|\n";
cout<<"| 9.- Salir
|\n";
cout<<"======================================\n";
cout<<"======================================\n";
cout<<"Ingrese Opcion: ";cin>>opc;
char opc0='s';
switch(opc)
{
case 1:
while(opc0=='s' || opc0=='S')
{
cout<<"=============================\n";
cout<<"Numero : ";cin>>valor;
InsertaAlInicio(lista,valor);
cout<<"Seguir ingresando [s/n]: ";cin>>opc0;
}
break;
case 2:
while(opc0=='s' || opc0=='S')
{
cout<<"=============================\n";
cout<<"Numero : ";cin>>valor;
InsertaAlFinal(lista,valor);
cout<<"Seguir ingresando [s/n]: ";cin>>opc0;
}
break;
case 3:
cout<<"=============================\n";
cout<<"Ingrese el valor a buscar: ";cin>>valor;
cout<<"\nListado\n";
Imprimir(lista);
R=Busqueda(lista,valor,pos);
if(R==true)
{
cout<<"\n\tValor buscado: "<<valor;
cout<<"\n\tEstado
: Existe";
cout<<"\n\tPosicion
: "<<pos;getch();
}
else
{
cout<<"\n\tValor buscado: "<<valor;
cout<<"\n\tEstado
: No Existe";
cout<<"\n\tPosicion
: Ninguna";
}
break;
case 4:
cout<<"=============================\n";
cout<<"\nElementos\n";
EliminarLista(lista);getch();
break;
case 5:
cout<<"=============================\n";
cout<<"\nListado\n";
Imprimir(lista);getch();
break;

ESTRUCTURA DE DATOS AVANZADOS

LISTAS DOBLES

case 6:
cout<<"=============================\n";
EliminaAlInicio(lista);
getch();
break;
case 7:
cout<<"=============================\n";
cout<<"Ingrese el valor a eliminar: ";cin>>valor;
cout<<"\nEl metodo eliminara todos los elementos que \ncoincidan con el valor ingresado
...\n";

EliminaElemento(lista,valor);
getch();
break;
case 8:
cout<<"=============================\n";
cout<<"\nLista Ordenada\n";
Ordenar(lista);
Imprimir(lista);getch();
break;
} //FIN DEL SWITCH
clrscr();
}while(opc!=9);

}
void InsertaAlInicio(Tlista &lista,int valor)
{
Tlista pos,nu;
nu = new (struct nodo);
nu->nro = valor;
pos = lista;
if(lista == NULL)
{
lista = nu;
lista->sgte = NULL;
lista->ante = NULL;
}
else
{
nu->sgte = lista;
nu->ante = lista->ante;
lista->ante = nu;
lista = nu;
}
}
void InsertaAlFinal(Tlista &lista,int valor)
{
Tlista pos,nu;
nu = new (struct nodo);
nu->nro = valor;
pos = lista;
if(lista == NULL)
{
lista = nu;
lista->sgte = NULL;
lista->ante = NULL;
}
else
{
while (pos->sgte!= NULL) { pos = pos->sgte; }
nu->sgte = pos->sgte;
pos->sgte = nu;
nu->ante = pos;
}
}

ESTRUCTURA DE DATOS AVANZADOS

LISTAS DOBLES

bool Busqueda(Tlista lista,int num,int& pos)


{
Tlista aux = lista;
pos=0;
while (aux != NULL)
{
if (aux->nro == num)
{
return true;
}
aux = aux->sgte;
pos++;
}
return false;
}
void EliminarLista(Tlista& lista)
{
lista = NULL;
}
void Imprimir(Tlista lista)
{
Tlista aux = lista;
int i = 0;
while (lista != NULL)
{
cout<<"N["<<i<<"] = {"<<lista->nro<<"}, ";
lista = lista->sgte;
i++;
}
if(i==0)
{
cout<<"\nLa lista no tiene datos ... Press Enter";
}
}
void EliminaAlInicio(Tlista& lista)
{
if(lista!=NULL) //Siempre que la lista tenga un valor
{
lista=lista->sgte;
cout<<"\nEliminado ... Press Enter ";
}
else
{
cout<<"\nLa lista no tiene datos ... Press Enter ";
}
}
void EliminaElemento(Tlista& lista,int ele)
{
Tlista aux=lista;
bool existe=false;
while (aux!= NULL)
{
if (aux->nro == ele)
{
if(aux->ante == NULL && aux->sgte == NULL)//Si el elemento se encuentra al inicio y es el unico
{
aux = NULL;
lista = aux;
goto fin;
}
else
{
if(aux->ante == NULL) //Si el elemento est al inicio

ESTRUCTURA DE DATOS AVANZADOS

LISTAS DOBLES

{
lista->sgte->ante = NULL;
lista = lista->sgte;
}
else
{
if(aux->sgte == NULL) //Si el elemento se encuentra al final
{
aux->ante->sgte = NULL;
aux = aux->ante;
}
else
//Si el elemento se encuentra en otra posicin
{
aux->ante->sgte = aux->sgte;
aux->sgte->ante = aux->ante;
aux = aux->ante;
}
}

}
existe = true;

aux = aux->sgte;
}
fin:
if(existe)
{
cout<<"\nELEMENTO ELIMINADO!! ... Press Enter";
}
else
{
cout<<"\nEl Elemento NO EXISTE en la Lista! ... Press Enter";
}
}
void Ordenar(Tlista& lista)
{
Tlista aux1,aux2;
if(lista!=NULL)
{
aux1 = lista, aux2 = lista->sgte;
int cambiar;
while (aux1 != NULL)
{
aux2 = aux1->sgte;
while (aux2 != NULL)
{
if (aux1->nro >= aux2->nro)
{
cambiar = aux1->nro;
aux1->nro = aux2->nro;
aux2->nro = cambiar;
}
aux2 = aux2->sgte;
}
aux1 = aux1->sgte;
}
}
}