Está en la página 1de 25

ELO320 Estructuras de Datos y Algoritmos

Listas

Tomás Arredondo Vidal

Este material está basado en:

 Robert Sedgewick, "Algorithms in C", (third edition), Addison-Wesley, ISBN 0-201-31663-3. 2001
 material del curso ELO320 del Prof. Leopoldo Silva
 material en el sitio http://es.wikipedia.org

5: Listas 1
5-Listas

5.1 Definiciones y operaciones


5.2 Listas simplemente enlazadas
5.3 Listas doblemente enlazadas
5.4 Listas circulares
5.5 Listas auto organizadas y ordenadas

5: Listas 2
Definiciones y operaciones

 Cada elemento o nodo se representa por una


estructura, cuyos campos pueden ser leídos y
escritos a través de un puntero a la estructura.
 Suele existir un campo que se denomina clave, que
identifica únicamente al nodo. La clave puede ser
numérica o alfanumérica.
 Operaciones posibles sobre listas incluyen:
 Recorrer
 Buscar
 Seleccionar
 Insertar
 Descartar
5: Listas 3
5-Listas

5.1 Definiciones y operaciones


5.2 Listas simplemente enlazadas
5.3 Listas doblemente enlazadas
5.4 Listas circulares
5.5 Listas auto organizadas y ordenadas

5: Listas 4
Listas simplemente enlazadas
 Listas que requieren un solo
enlace (puntero) entre un nodo
y su sucesor
 Elementos se direccionan en
tiempo constante O(1), los
elementos tienen un costo de
acceso de O(n) en el peor caso
 Las operaciones deben
considerar que estas listas
pueden estar vacías lo cual
requiere un tratamiento
especial
 El uso de un centinela
simplifica las operaciones al
hacer que todos los nodos sean
tratados de forma igual
5: Listas 5
Ejemplo: Lista simplemente enlazada
typedef struct moldenodo
pnodo lista=NULL;
{
int clave;
struct moldenodo *proximo;
} nodo, *pnodo;

pnodo CreaNodo(int dato)


{ pnodo pn=NULL;
pnodo listaC = CreaNodo(0);
if ( (pn= (pnodo) malloc(sizeof(nodo))) ==NULL) exit(1);
else
{ pn->clave=dato;
pn->proximo=NULL;
}
return(pn);
}

5: Listas 6
Ejemplo: Recorrer la lista y contar nodos
int LargoLista(pnodo p)
{ int numeroelementos = 0;
while (p != NULL)
{
numeroelementos ++;
p = p ->proximo; //recorre la lista
}
return (numeroelementos);
}

int LargoLista(pnodo p)
{ int numeroelementos = 0;
for ( ; p != NULL; p=p->proximo) numeroelementos ++;
return (numeroelementos);
}

5: Listas 7
Ejemplo: Buscar un nodo
pnodo Buscar(pnodo p, int valor) pnodo q;
{ while (p != NULL) if ( (q= Buscar(lista, 5)) == NULL)
{ /* no encontró nodo con clave = 5*/
{
}
if (p->clave== valor)
else
return (p); //lo encontró
{ /* lo encontró. …..*/
else p = p ->proximo; //recorrer: O(n) }
}
return (p); //retorna NULL si no lo encontró. if ( (q= Buscar(listaC->proximo, 5)) == NULL)
} { /* no encontró nodo con clave = 5*/
}
else
Como usar esta función?
{ /* lo encontró. …..*/
}

5: Listas 8
Ejemplo: Seleccionar un valor extremo (mínimo)
pnodo SeleccionarMinimo(pnodo p)
{ int min; pnodo t;
if (p==NULL) return (NULL);
else
{ min=p->clave; //Inicia min
t=p;
p=p->proximo;
}
while (p != NULL)
{ if (p->clave <min )
{ min=p->clave;
t=p;
}
p = p ->proximo; //recorre la lista. O(n)
}
return (t);
}

5: Listas 9
Ejemplo: Buscar el último nodo

pnodo ApuntarAlFinal(pnodo p) // como programar?


{
pnodo t;
if (p==NULL)
{
return (NULL);
}
else while (p != NULL)
{
t=p;
p = p ->proximo; //recorre la lista. O(n)
}
return (t);
}

5: Listas 10
Listas: inserción
 Hay dos variables de tipo puntero a
nodo: p apunta a un nodo de una
lista y n apunta a un nodo
correctamente inicializado (e.g.
retorno de CreaNodo).
 El nodo apuntado por n puede ser
insertado después del nodo
apuntado por p usando:
n->proximo = p->proximo;
 Para completar la lista se usa:
p->proximo = n;
 Como seria el diagrama final?

5: Listas 11
Ejemplo: insertar después  Ejemplo de uso:
 Si el argumento posición toma valor pnodo lista=NULL; //inicializar lista
NULL, se producirá un error, por pnodo pos=NULL;
eso se verifica su existencia,
lista=InsDespues(pos, CreaNodo(1));
pnodo InsDespues( pnodo posicion,
pnodo nuevo)
pos =Buscar(lista, 1);
{ InsDespues(pos, CreaNodo(2));
if (nuevo == NULL) pos =Buscar(lista, 2);
return (NULL);
InsDespues(pos, CreaNodo(3));
if (posicion != NULL)
pos =Buscar(lista, 2);
{ nuevo->proximo = posicion->proximo;
posicion->proximo=nuevo; InsDespues(pos, CreaNodo(4));
return (posicion);
}
return(nuevo);
}

5: Listas 12
Listas: inserción antes
 Si se desea insertar antes de la posición p; se
requiere una variable temporal para efectuar p

el intercambio (i.e. temp) :


1 2
pnodo p = NULL; //inicializar lista n
p = InsDespues(p,CreaNodo(1));
3
InsDespues(p,CreaNodo(2));
pnodo n = CreaNodo(3);
// Como es el diagrama?
int temp;
n->proximo = p->proximo;
p->proximo = n;
temp=p->clave;
p->clave=n->clave;
n->clave=temp;
// Como es el diagrama final?
5: Listas 13
Listas: inserción al final
 Si se desea insertar al final:
pnodo InsertaNodoalFinal(pnodo posicion, int dato)
{ pnodo temp=posicion;
if (temp != NULL)
{
while (temp->proximo !=NULL)
temp=temp->proximo; //O(n)
temp->proximo=CreaNodo(dato);
return (temp->proximo); //retorna NULL si no se pudo crear
}
else
return (CreaNodo(dato));
} // Ejemplo uso?
5: Listas 14
Inserción: cabeza y cola
 Usando variables globales
cabeza y cola:
static pnodo cabeza=NULL;
static pnodo cola=NULL;
 Insertafinal( )?
pnodo insertainicio(int clave) pnodo insertafinal(int clave)
{ pnodo t=CreaNodo(clave); { pnodo t =CreaNodo(clave);
if(cabeza==NULL) if(cola==NULL) { cola=cabeza=t;}
else {
cola=t;
cola->proximo=t; cola=t;} //O(1)
t->proximo=cabeza; return(t);
cabeza=t; //O(1) }
return(t);
}
5: Listas 15
Inserción con referencias
 Usando referencias:  Uso?:

void ins_nodo_ref(pnodo *p, pnodo t) pnodo lista1=NULL;


{ if (*p==NULL) Insertanodo_ref(&lista1,
CreaNodo(4));
*p=t; //inserta en lista vacía.
Insertanodo_ref(&lista1,
else {
CreaNodo(3));
t->proximo=*p; //lee var. externa.
Insertanodo_ref(&lista1,
*p=t; //escribe en var. externa. CreaNodo(2));
} Insertanodo_ref(&lista1,
} CreaNodo(1));

5: Listas 16
Listas: descarte
 La variable p apunta al nodo
anterior al que se desea descartar,
 t apunta al nodo que se desea
desligar de la lista después de
ejecutada la acción:
t=p->proximo;
 Para mantener la lista ligada:

p->proximo = t->proximo;
 Después se libera el espacio del
nodo descartado:
free(t);
t=NULL;
5: Listas 17
5-Listas

5.1 Definiciones y operaciones


5.2 Listas simplemente enlazadas
5.3 Listas doblemente enlazadas
5.4 Listas circulares
5.5 Listas auto organizadas y ordenadas

5: Listas 18
Listas doblemente enlazadas
 Estas listas requieren dos
enlaces (punteros) entre un nodo,
su sucesor y su antecesor:

typedef struct moldecelda


{ int clave;
struct moldecelda *nx; //next struct
struct modecelda *pr; // previous
} nodo, *pnodo;

5: Listas 19
Listas doblemente enlazadas: insertar después
 Diagramas muestran las variables
antes de insertar el nodo apuntado
por q a la lista dada por p.
 Como seria el código para insertar?
q->nx = p->nx;
q->pr = p;
p->nx = q ;
q->nx->pr = q;
 Como seria descartar el nodo q?
q->pr->nx = q->nx;
q->nx->pr = q->pr;
free(q);
5: Listas 20
Listas doblemente enlazadas: condiciones
 Las operaciones de insertar, buscar y descartar deben
considerar las condiciones en los bordes, y que la lista
pueda estar vacía.
 Una forma usual de tratar simplificadamente las
condiciones de borde, es definir un nodo vacío, denominado
cabecera o centinela.

5: Listas 21
5-Listas

5.1 Definiciones y operaciones


5.2 Listas simplemente enlazadas
5.3 Listas doblemente enlazadas
5.4 Listas circulares
5.5 Listas auto organizadas y ordenadas

5: Listas 22
Listas circulares
 En listas simplemente enlazadas, sin o con cabecera,
puede escogerse que el último nodo apunte al primero,
con esto se logra que el primer nodo pueda ser
cualquier nodo de la lista.

 La inserción al inicio, en el caso de la figura debe


tratarse de manera especial, con costo O(n), para que
el último nodo apunte al nuevo primero.
 Si la lista es con centinela, y si el último apunta al
centinela, no es necesario introducir código adicional.
5: Listas 23
5-Listas

5.1 Definiciones y operaciones


5.2 Listas simplemente enlazadas
5.3 Listas doblemente enlazadas
5.4 Listas circulares
5.5 Listas auto organizadas, ordenadas

5: Listas 24
Listas auto organizadas y ordenadas
 En listas auto organizadas la operación buscar
mueve a la primera posición el elemento
encontrado.
 De esta manera los elementos más buscados van
quedando cerca del inicio.
 En listas ordenadas se mantienen los nodos
ordenados según el orden de las claves.
 Se puede tratar las listas en base a arreglos.
Pudiendo ser éstos: arreglos de nodos, en los
cuales se emplean punteros; o bien arreglos que
contienen la información de vínculos en base a
cursores que almacenan índices.
5: Listas 25

También podría gustarte