LISTAS ENLAZADAS
PARTE 1
CLASE N°6
CLASE N°6
Leissi M. Castañeda León
Que veremos hoy?
1. Introducción
1. Introducción
Las estructura de datos como arreglos y registros, se
denominan estáticas (durante la compilación se le
asigna un espacio de memoria, y no se altera durante la ejecución)
La estructura de datos lista, es lineal (cada elemento le La estructura de datos lista, es lineal (cada elemento le
puede seguir a otro) y dinámica (manejar memoria de manera flexible) de datos.
VENTAJA principal: dinamismo, se puede adquirir
posiciones de memoria y liberar a medida que se necesiten.
Considerar que NO pueden reemplazar en todas las
Introducción
Las listas enlazadas son colecciones de elementos
llamados nodos; el orden entre éstos se establece por medio de un tipo de datos denominado punteros,
apuntadores o referencias a otros nodos.
Entonces se podrá distinguir: el dato de tipo apuntador y Entonces se podrá distinguir: el dato de tipo apuntador y
el dato contenido en la celda al cual éste apunta.
Operaciones más importantes: búsqueda (no muy
eficiente), inserción y eliminación.
Tipos:
Listas Simplemente Enlazadas
Una LSE constituye una colección de elementos
llamados nodos.
El orden entre los nodos se establece por punteros
(referencias a otros nodos).
Un tipo especial: la lista vacía Un tipo especial: la lista vacía
Un nodo está formado por:
Un campo INFORMACIÓN, del tipo de dato que se quiere
almacenar.
Un campo ENLACE, de tipo puntero, para enlazar con otro nodo.
Estructura Nodo para una LSE
typedef struct Nodo
{
int dato;
struct Nodo *sgt;
INFORMACIÓN
ENLACE
struct Nodo *sgt;
} TNodo;
Creando un puntero cabecera
Crearemos un puntero, de tipo de la estructura
Nodo (Tnodo), que apunte al nodo inicial de la
LSE
typedef struct LSE
{
Para crear una lista vacía
Crea una lista devolviendo un puntero Tnodo
TLSE *crearLista()
{{
TLSE *l=(TLSE*)malloc(sizeof(struct LSE));
l->pInicio=NULL;
return l;
}
pInicio
Ejemplo
NULL
2 1
4
Operaciones con LSE
Recorrido de la lista
Iterativo Recursivo
Inserción de un elemento Inserción de un elemento
Al Inicio Al Final
Operaciones con LSE
Eliminación de un elemento
El primer nodo El último nodo
Eliminar un nodo con información X
Eliminar el nodo anterior al nodo con información X Eliminar el nodo anterior al nodo con información X Eliminar el nodo posterior al nodo con información X
Búsqueda de un elemento
Recorrido de la lista
Esta operación consiste en visitar cada uno de los nodos
que forman la lista. La visita puede implicar una
operación simple; por ejemplo, imprimir la información del nodo, o una compleja, dependiendo del problema que se intente resolver.
Para recorrer todos los nodos de una LSE se comienza
con el primero. Se toma el valor del campo ENLACE de éste y se avanza al segundo, así hasta llegar al último nodo, cuyo campo ENLACE tenga el valor NULL.
En general, la dirección de un nodo, excepto el primero
Recorrido de la lista:
Iterativa
/*Imprimiremos los datos en el recorrido iterativo de la lista*/
void recorridoIterativo(TLSE *lista) {
TNodo *p=NULL; p=lista->pInicio; p=lista->pInicio; while(p!=NULL) {
printf(" %d ->",p->dato); p=p->sgt;
Recorrido de la lista:
Recursiva
/*Imprimiremos los datos en el recorrido recursivo de la lista*/
void recorridoRecursivo(TNodo *p) {
if(p!=NULL) {{
printf(" %d ->",p->dato);
recorridoRecursivo(p->sgt); }
}
Inserción de un elemento
Esta operación en las LSE consiste en agregar un nuevo
nodo a la lista.
Dependiendo de la posición en la que se deba insertar el
nodo, se pueden presentar diferentes casos, como los nodo, se pueden presentar diferentes casos, como los que se señalan a continuación:
Al Inicio Al Final
Inserción: al
Inicio
de la lista
void insertarInicio(int dato, TLSE *lista) {
TNodo *nodo=NULL;
nodo=(TNodo*)malloc(sizeof(struct Nodo)); nodo->dato=dato;
nodo->dato=dato;
nodo->sgt=lista->pInicio; lista->pInicio=nodo;
Inserción: al
Final
de la lista
void insertarFinal(int dato, TLSE *lista) {
TNodo *p=NULL, *nodo=NULL;
nodo=(TNodo*)malloc(sizeof(struct Nodo)); nodo->dato=dato;
nodo->sgt=NULL;
p=lista->pInicio;
if(p==NULL) //si la lista está vacía
{
Inserción: al
Final
de la lista (cont.)
else //si la lista NO está vacía
{
while(p->sgt!=NULL) {
p=p->sgt; }
p->sgt=nodo; }
Inserción:
Antes
que otro
void insertarAntes(int dato, TLSE *lista, int X) {
TNodo *p=NULL, *ant=NULL; int band=1;
p=lista->pInicio; if(p==NULL)
{ band=0; } else
else {
while((p->dato!=X) && (band==1)) {
if(p->sgt!=NULL) { ant=p;
p=p->sgt; }
else
Inserción: Antes que otro
if(band==1) //si se encontró el nodo referencia: X
{
TNodo *nodo=NULL;
nodo=(TNodo*)malloc(sizeof(struct Nodo)); nodo->dato=dato;
nodo->sgt=NULL;
if(ant==NULL) //si se va a insertar al inicio
{ nodo->sgt=p; lista->pInicio=nodo; lista->pInicio=nodo; } else { ant->sgt=nodo; nodo->sgt=p; } } else
Inserción:
Después
de otro
void insertarDespues(int dato, TLSE *lista, int X) {
TNodo *p=NULL; int band=1;
p=lista->pInicio; if(p==NULL)
{ band=0; } { band=0; } else
{
while((p->dato!=X) && (band==1)) {
if(p->sgt!=NULL)
{ p=p->sgt; }
else
Inserción: Después de otro (cont.)
if(band==1) {
TNodo *nodo=NULL;
nodo=(TNodo*)malloc(sizeof(struct Nodo)); nodo->dato=dato;
nodo->sgt=p->sgt; p->sgt=nodo;
p->sgt=nodo; }
else
printf("El nodo de referencia no se encontró en la lista\n"); }
Eliminación de un elemento
Consiste en eliminar un nodo de la lista y liberar el
espacio de memoria correspondiente.
Dependiendo de la posición en la que se encuentre, se
pueden presentar diferentes casos, como los que se señalan a continuación:
señalan a continuación:
El primer nodo El último nodo
Eliminar un nodo con información X
Eliminar: el
Primer
nodo
void eliminarInicio(TLSE *lista)
{
TNodo *p=lista->pInicio;
lista->pInicio=p->sgt;
lista->pInicio=p->sgt;
free(p);
Eliminar: el
Último
nodo
void eliminarFinal(TLSE *lista) {
TNodo *p=lista->pInicio, *ant=NULL; if(p!=NULL)
{
if(p->sgt!=NULL) {
while((p->sgt!=NULL)) while((p->sgt!=NULL))
{ ant=p;
p=p->sgt; }
ant->sgt=NULL; }
else
Eliminar: nodo
con
información
X
void eliminarNodoX(TLSE *lista, int X) {
TNodo *p=NULL, *ant=NULL; int band=1;
p=lista->pInicio; if(p==NULL)
{ band=0; } else
else {
while((p->dato!=X) && (band==1)) {
if(p->sgt!=NULL) { ant=p;
p=p->sgt; }
else
Eliminar: nodo con información X
(cont.)
if(band==1) {
if(ant==NULL) //si es el primer nodo {
lista->pInicio=p->sgt; }}
else {
ant->sgt=p->sgt; }
free(p); }
else
Eliminar: nodo
Anterior
al nodo X
void eliminar_Antes_X(TLSE *lista, int X) {
TNodo *p=NULL, *ant=NULL, *q=NULL; int band=1;
p=lista->pInicio; if(p==NULL)
band=0; else
{
while((p->dato!=X) && (band==1)) {
if(p->sgt!=NULL) { q=ant; ant=p;
p=p->sgt; }
Eliminar: nodo Anterior al nodo X
if(band==1) {
if(ant==NULL) //si p es el primer nodo {
printf("No existe nodo que preceda a el nodo de referencia: %d", X,"\n"); }
else {{
if(ant!=NULL && q==NULL) //se va a eliminar el primer nodo lista->pInicio=p;
else
q->sgt=p; }
free(ant); }
else
Eliminar: nodo
Posterior
al nodo X
void eliminar_Despues_X(TLSE *lista, int X) {
TNodo *p=NULL, *q=NULL; int band=1;
p=lista->pInicio; if(p==NULL)
band=0; else
{
while((p->dato!=X) && (band==1)) {
if(p->sgt!=NULL)
p=p->sgt; else
Eliminar: nodo Posterior al nodo X
if(band==1) {
if(p->sgt==NULL) //si p es el ultimo nodo {
printf("No existe nodo posterior a el nodo de referencia: %d ",X,"\n"); }
else else {
q=p->sgt;
p->sgt=q->sgt; }
free(q); }
else
Búsqueda de un elemento
Esta operación en una LSE es muy simple de realizar,
aunque ineficiente ya que se lleva a cabo de forma secuencial.
Debemos ir recorriendo los nodos hasta encontrar el que
estamos buscando o hasta que se llegue al final de la estamos buscando o hasta que se llegue al final de la lista.
Al igual que en el caso de las operaciones vistas
Búsqueda: en lista
Desordenada
Asumimos que la LSE se encuentra desordenada
void busquedaDesordenada(TLSE *lista, int X) {
TNodo *p=lista->pInicio; if(p!=NULL)
{{
while((p!=NULL) && (p->dato!=X)) p=p->sgt;
if(p==NULL)
printf("No se encontro el elemento en la lista\n"); else
printf("Si se encontro el elemento en la lista\n"); }
else
Búsqueda: en lista
Ordenada
Asumimos que la LSE se encuentra ordenada
void busquedaOrdenada(TLSE *lista,int X) {
TNodo *p=lista->pInicio; if(p!=NULL)
{{
while((p!=NULL) && (p->dato<X)) p=p->sgt;
if((p==NULL) || (p->dato>X))
printf("No se encontro el elemento en la lista\n"); else
printf("Si se encontro el elemento en la lista\n"); }
else
Búsqueda: en forma
Recursiva
void busquedaRecursiva(TNodo *p,int X) {
if(p!=NULL) {
if(p->dato==X)
printf("Si se encontro el elemento en la lista\n"); else
busquedaRecursiva(p->sgt,X); }
else