You are on page 1of 37

LISTAS ENCADENADAS

LISTAS ENCADENADAS
Las estructuras dinmicas nos permiten crear estructuras de datos que se adapten a las necesidades reales a las que suelen enfrentarse nuestros programas. Flexibles, ya sea en cuanto al orden, la estructura interna o las relaciones entre los elementos que las componen. La forma ms simple de estructura dinmica es la lista simplemente enlazada. En esta forma los nodos se organizan de modo que cada uno apunta al siguiente, y el ltimo no apunta a nada, es decir, el puntero del nodo siguiente vale NULL.

LISTAS ENCADENADAS
Son estructuras de datos similares a los arreglos, pero; su diferencia principal radica en que mientras que en un arreglo los elementos estn contiguos en la memoria, en una lista los elementos estn dispersos. El enlace entre los elementos se hace mediante un puntero. La forma de insercin de nuevos elementos depende de lo que se pretenda conseguir con la implementacin de la Lista (Principio, izquierda, centro, derecha, final etc.).

LISTAS ENCADENADAS
Una lista enlazadas estn compuestas de pequeas estructuras a las que llamaremos nodos o elementos, que agrupan los datos con los que trabajar nuestro programa y adems uno o ms punteros autoreferenciales, es decir, punteros a objetos del mismo tipo nodo. El modelo bsico de definicin en C de un elemento de la Lista sera el siguiente: struct tnodo { int dato; struct tnodo *siguiente; }; Para este ejemplo, cada elemento de la lista slo contiene un dato de tipo entero, pero en la prctica no hay lmite en cuanto a la complejidad de los datos a almacenar.

LISTAS ENCADENADAS
En las listas abiertas existe un nodo especial: el primero. Normalmente diremos que nuestra lista es un puntero a ese primer nodo y llamaremos a ese nodo la cabeza de la lista. Eso es porque mediante ese nico puntero podemos acceder a toda la lista.

Cuando el puntero que usamos para acceder a la lista vale NULL, diremos que la lista est vaca.

LISTAS ENCADENADAS
Para el manejo de listas en C C++ se hace necesario la definicin de varios tipos que facilitan el manejo de la misma. La declaracin de tipos puede tener una forma parecida a la siguiente:
typedef struct tnodo { int dato; struct tnodo *Sig; } tipoNodo; typedef tipoNodo *pNodo;// tipo punteros a nodos typedef tipoNodo *Lista;// tipo listas

LISTAS ENCADENADAS
Donde la parte del nodo correspondiente a los datos va a depender de la informacin que se necesite manejar : typedef struct tdato { char fecha [12], autor[30] ; int tamano;} tipodato; typedef tipodato Tdato; typedef struct tnodo { Tdato dato; struct tnodo *Sig; } tipoNodo;
7

LISTAS ENCADENADAS
Operaciones bsicas que se pueden realizar sobre una lista: Aadir o insertar elementos. Buscar o localizar elementos. Borrar elementos. Moverse a travs de una lista, anterior, siguiente, primero. Cada una de estas operaciones tendr varios casos especiales, por ejemplo, no ser lo mismo insertar un nodo en una lista vaca, o al principio de una lista no vaca, o al final, o en una posicin intermedia.

LISTAS ENCADENADAS
INSERTAR ELEMENTOS Para insertar un nuevo elemento en una lista enlazada es necesario crear el nuevo nodo, reservando espacio con el operador new y guardar los datos en cada campo del registro apuntado. Siguiendo unas instrucciones similares a las siguientes:
pNodo NUEVO; NUEVO = new(tipoNodo); // reserva de memoria if NUEVO // es != NULL {NUEVO ->Info = X; } NUEVO ->Sig = NULL; // inicializar siguiente

LISTAS ENCADENADAS
INSERTAR ELEMENTOS: CASOS Insertar un elemento en una lista vaca

El proceso es muy simple, bastar con que: 1. nodo->Sig apunte a NULL. 2. Lista apunte a nodo.

10

LISTAS ENCADENADAS
Insertar un elemento en la primera posicin de una lista

El proceso sigue siendo muy sencillo: 1. Hacemos que nodo->Sig apunte a Lista. 2. Hacemos que Lista apunte a nodo.

11

LISTAS ENCADENADAS
El procedimiento para insertar un elemento en la primera posicin de una lista este vaca o no puede ser de la siguiente forma: void INSERTAR_INI(pNodo &Lista, DATO Elem) { pNodo NUEVO; NUEVO=new(tipoNodo); if (NUEVO) { NUEVO->Info=Elem; NUEVO->Sig=NULL; if(Lista==NULL) Lista=NUEVO; // Lista Vacia else { NUEVO->Sig=Lista; Lista=NUEVO; } } }

12

LISTAS ENCADENADAS
Insertar un elemento al final de una lista

Para este caso se parte de una lista no vaca

El proceso consiste en: 1. Ubicar un puntero que seale al ltimo elemento de la lista. La manera de conseguirlo es empezar por el primero y avanzar hasta que el nodo tenga como siguiente el valor NULL.
13

LISTAS ENCADENADAS
Por ejemplo: pNodo Lista, ultimo; If (Lista != NULL) {ultimo= Lista; while (ultimo-> Sig !=NULL) ultimo= ultimo-> Sig; } 2. Hacer que nodo->Sig sea NULL. 3. Hacer que ultimo->Sig sea nodo.

14

LISTAS ENCADENADAS
El procedimiento para insertar al final queda de la siguiente manera: void INSERTAR_FIN(pNodo &Lista, DATO Elem) { pNodo A = Lista; pNodo NUEVO; NUEVO = new (tipoNodo); NUEVO->Info = Elem; NUEVO->Sig = NULL; if(Lista == NULL) Lista = NUEVO; else {while (A->Sig != NULL) A=A->Sig; A->Sig = NUEVO; } }
15

LISTAS ENCADENADAS
Insertar un elemento en una posicin solicitada de la lista:

El proceso a seguir ser similar a: 1. Localizar el nodo anterior a uno determinado pNodo anterior= Lista; i=1; // POS es un nro de nodo a localizar while(i<POS-1 && anterior->Sig != NULL) {i++; anterior=anterior->Sig;}

16

LISTAS ENCADENADAS
Encadenar el nuevo nodo

1. Hacer que nodo->Sig seale a anterior->Sig. 2. Hacer que anterior->Sig seale a nodo.

17

LISTAS ENCADENADAS
Ej.: Procedimiento para insertar elementos despus de un nodo que cumple con una condicin:
void INSERTAR_NODO(pNodo &Lista, DATO X, int POS) { int i; pNodo A= Lista, NUEVO; NUEVO = new( tipoNodo); if NUEVO { NUEVO ->Info = X; NUEVO ->Sig = NULL; if(POS==1 || Lista==NULL) { NUEVO->Sig = Lista; Lista = NUEVO; } else { i=1; while(i<POS-1 && A->Sig != NULL) { i++; A=A->Sig;} if(A->Sig != NULL) { NUEVO->Sig = A->Sig; A->Sig= NUEVO; } else A->Sig=NUEVO; }}

18

LISTAS ENCADENADAS
Ej.: Procedimiento para insertar elementos de forma ordenada en una lista:
void Insertar(Lista &lista, int v) { pNodo nuevo, anterior; nuevo = new tipoNodo; //Crear un nodo nuevo nuevo->valor = v; if(ListaVacia( lista) || (lista->valor > v) //Si la lista est vaca { nuevo->Sig = lista; lista = nuevo; } else {anterior = lista; //Buscar el nodo de valor menor a v while(anterior->Sig && anterior->Sig->valor <= v) anterior = anterior->Sig; nuevo->Sig = anterior->Sig; anterior->Sig = nuevo; } }
19

LISTAS ENCADENADAS
LOCALIZAR ELEMENTOS EN UNA LISTA: Para recorrer una lista procederemos siempre del mismo modo, usaremos un puntero auxiliar como ndice, para hacer el recorrido: 1. Asignamos al puntero ndice el valor de Lista. 2. Abriremos un ciclo que al menos debe tener una condicin, que el ndice no sea NULL. 3. Dentro del ciclo asignaremos al ndice el valor del nodo siguiente al ndice actual.

20

LISTAS ENCADENADAS
Procedimiento que permite realizar la bsqueda de un elemento en la lista y devuelve la direccin del nodo donde se encuentra el elemento: pNodo BUSCAR_DIR(pNodo Lista, DATO elem) { pNodo A=Lista; if(Lista!=NULL) { while(A->Info!=elem && A->Sig!=NULL) A=A->Sig; if(A->Info==elem) return A; else return NULL; } else { cout<<"Lista Vacia "<<endl; return NULL; } }

21

LISTAS ENCADENADAS
Procedimiento que determina si un dato existe o no en la lista y devuelve 1 si existe y 0 sino se encuentra: int EXISTE(pNodo Lista, DATO X) { pNodo A=Lista; if(Lista!=NULL) {while(A->Info!=X && A->Sig!=NULL) A=A->Sig; if(A->Info==elem) return 1; else return 0; } else { cout<<"Lista Vacia "<<endl; return 0;} }
22

LISTAS ENCADENADAS
ELIMINAR ELEMENTOS EN UNA LISTA ABIERTA: CASOS Eliminar el primer nodo de una lista abierta: Partiremos de una lista con uno o ms nodos, y usaremos un puntero auxiliar, nodo:

1. Hacemos que nodo apunte al primer elemento de la lista, es decir a Lista. 2. Asignamos a Lista la direccin del segundo nodo de la lista: Lista->Sig.
23

LISTAS ENCADENADAS
3. Liberamos la memoria asignada al primer nodo, el que queremos eliminar.

Si no guardamos el puntero al primer nodo antes de actualizar Lista, despus nos resultara imposible liberar la memoria que ocupa. Si liberamos la memoria antes de actualizar Lista, perderemos el puntero al segundo nodo.
24

LISTAS ENCADENADAS
Eliminar un nodo cualquiera de una lista abierta:

1. Localizamos el nodo que queremos eliminar, hacemos que una variable auxiliar anterior apunte al nodo anterior que se quiere borrar. 2. Ahora, asignamos como nodo siguiente del nodo anterior, el siguiente al que queremos eliminar: anterior->Sig = nodo->Sig. 3. Eliminamos la memoria asociada al nodo que queremos eliminar

25

Procedimiento para localizar y eliminar un elemento de la lista:


void Borrar(Lista &lista, int v) { pNodo anterior, nodo; nodo = lista; anterior = NULL; while(nodo && nodo->dato < v) { anterior = nodo; nodo = nodo->Sig; } if(!nodo || nodo->dato != v) return; else { if(!anterior) // Primer elemento lista = nodo->Sig; else // un elemento cualquiera anterior->Sig = nodo->Sig; delete nodo; } }
26

LISTAS ENCADENADAS

LISTAS ENCADENADAS
Procedimiento para borrar todos los nodos de una lista: void BorrarLista(Lista &lista) { pNodo nodo; while(lista) { nodo = lista; lista = nodo->Sig; delete nodo; }}

27

LISTAS ENCADENADAS
Moverse a travs de una lista: Slo hay un modo de moverse a travs de una lista enlazada simple, hacia delante. An as, a veces necesitaremos acceder a determinados elementos de una lista abierta. Veremos ahora como acceder a los ms corrientes: el primero, el ltimo, el siguiente y el anterior.

Primer elemento de la lista El primer elemento es el ms accesible, ya que es a ese a que apunta el puntero que define la lista. Para obtener un puntero al primer elemento bastar con copiar el puntero Lista.

28

LISTAS ENCADENADAS
Procedimiento para localizar el anterior a un nodo P No es posible retroceder en una lista, de modo que para obtener un puntero al nodo anterior a uno dado tendremos que partir del primero, e ir avanzando hasta que el nodo siguiente sea precisamente nuestro nodo.
pNodo ANTERIOR(pNodo Lista, pNodo P) { pNodo A=Lista; if(Lista==NULL || P==NULL || Lista==P) return NULL; else { while(A->Sig!=P && A->Sig!=NULL) A=A->Sig; if(A->Sig==P) return A; else return NULL; } }

29

LISTAS ENCADENADAS
Procedimiento que permite localizar el anterior a un nodo en una lista ordenada: pNodo ANTERIOR_O(pNodo Lista, DATO Elem) { ptNodo P=NULL,A=Lista; if(A != NULL) { while(Elem>=A->Info && A->Sig!=NULL) { P=A; A=A->Sig; } if(Elem>=A->Info) P=A; } return P; }
30

LISTAS ENCADENADAS
Procedimiento para localizar el siguiente a un nodo P Supongamos que tenemos un puntero P que seala a un elemento de una lista. Para obtener un puntero al siguiente bastar con asignarle el campo "siguiente" del nodo, P->siguiente.
pNodo SIGUIENTE(pNodo Lista, pNodo P) { pNodo nodo=Lista; if(Lista==NULL || P==NULL || Lista==P) return NULL; else {while(nodo!=NULL && nodo!=P) nodo=nodo->Sig; if(nodo==P) return nodo->Sig; else return NULL; } }

31

Ultimo Elemento de la lista: Para obtener un puntero al ltimo elemento de una lista partiremos de un nodo cualquiera, por ejemplo el primero, y avanzaremos hasta que su nodo siguiente sea NULL.
pNodo ULTIMO (pNodo Lista, pNodo P) { pNodo A=Lista; if(Lista==NULL ) return NULL; else {while(A->Sig!=NULL) A=A->Sig; return A;}}

LISTAS ENCADENADAS

Procedimiento ListaVacia: Basta con comparar el puntero Lista con NULL, si Lista vale NULL la lista est vaca.
int ListaVacia(Lista lista) { return (lista == NULL);}
32

LISTAS ENCADENADAS
Visualizacin de una lista: Para mostrar la lista entera hay que posicionarse al principio de la misma, luego utilizar el puntero a Siguiente de cada elemento de la lista. La condicin de parada es dada por el puntero Sig del ultimo elemento que vale NULL void MostrarLista(pNodo lista) { pNodo nodo = lista; if(ListaVacia(lista)) printf ("Lista vaca\n"); else { while(nodo) { printf ("%d -> ", nodo->dato); nodo = nodo->Sig;} printf("\n"); }}
33

LISTAS ENCADENADAS
Ej.: Muestra los elementos de una lista hasta conseguir un dato que sea mayor que 100: typedef struct nodo { int dato; struct nodo *Sig; } tipoNodo; typedef tipoNodo *pNodo; typedef tipoNodo *Lista;.
pNodo indice; ... indice = Lista; while(indice && indice->dato <= 100) { printf("%d\n", indice->dato); indice = indice->Sig;}

34

En el ejemplo anterior, si analizamos la condicin del ciclo, tal vez encontremos un posible error: Podra pensarse que cuando indice sea NULL, si intentamos acceder a indice->dato se producir un error. En general eso ser cierto, no puede accederse a punteros nulos. Pero en este caso, ese acceso est dentro de una condicin y forma parte de una expresin "and". Recordemos que cuando se evala una expresin "and", se comienza por la izquierda, y la evaluacin se abandona cuando una de las expresiones resulta falsa, de modo que la expresin "indice->dato <= 100" nunca se evaluar si indice es NULL. Si hubiramos escrito la condicin al revs, el programa nunca funcionara bien. Esto es algo muy importante cuando se trabaja con punteros.
35

LISTAS ENCADENADAS

LISTAS ENCADENADAS
EJEMPLO: Escribir una funcin que permita invertir el contenido de una lista . void INVERTIR ( pNodo &Lista) { pNodo aux=Lista, X=NULL; while (aux!=NULL) { INSERTAR_INI(X, aux->info); Lista=Lista->Sig: delete (aux); aux=Lista; } Lista=X; }
36

LISTAS ENCADENADAS
Ej.: Escribir una funcin que divida una lista en dos sub-listas, pero; alternando los elementos entre ambas listas. void DIVIDIR ( pNodo Lista, pNodo &X, pNodo &Y) {int bandera=0; pNodo aux=Lista; while (aux!=NULL) { if (bandera==0) { INSERTAR_FIN(X, aux->info); bandera=1; } else {INSERTAR_FIN(Y, aux->info); bandera=0; } aux=aux->Sig; } }
37

You might also like