You are on page 1of 15

UNIVERSIDAD DON BOSCO

DEPARTAMENTO DE INFORMTICA

Listas

INSTRUCTOR: Guillermo Prez.

GRADO: 3 Informtica PILET

N 1

Apellidos Navarrete Alemn

Nombres Astrid Gabriela

NOTA:

OBSERVACIONES:

Lista
Una lista enlazada es una de las estructuras de datos fundamentales, y puede ser usada para implementar otras estructuras de datos. Consiste en una secuencia de nodos, en los que se guardan campos de datos arbitrarios y una o dos referencias, enlaces o punteros al nodo anterior o posterior. El principal beneficio de las listas enlazadas respecto a los vectores convencionales es que el orden de los elementos enlazados puede ser diferente al orden de almacenamiento en la memoria o el disco, permitiendo que el orden de recorrido de la lista sea diferente al de almacenamiento. Una lista enlazada es un tipo de dato autorreferenciado porque contienen un puntero o enlace a otro dato del mismo tipo. Las listas enlazadas permiten inserciones y eliminacin de nodos en cualquier punto de la lista en tiempo constante (suponiendo que dicho punto est previamente identificado o localizado), pero no permiten un acceso aleatorio. Existen diferentes tipos de listas enlazadas: listas enlazadas simples, listas doblemente enlazadas, listas enlazadas circulares y listas enlazadas doblemente circulares. Las listas enlazadas pueden ser implementadas en muchos lenguajes. Lenguajes tales como Lisp y Scheme tiene estructuras de datos ya construidas, junto con operaciones para acceder a las listas enlazadas. Lenguajes imperativos u orientados a objetos tales como C o C++ y Java, respectivamente, disponen de referencias para crear listas enlazadas.

Tipos de listas enlazadas


Listas enlazadas lineales
Listas simples enlazadas
La lista enlazada bsica es la lista enlazada simple la cual tiene un enlace por nodo. Este enlace apunta al siguiente nodo en la lista, o al valor NULL o a la lista vaca, si es el ltimo nodo.

Listas doblemente enlazadas


Un tipo de lista enlazada ms sofisticado es la lista doblemente enlazada o lista enlazadas de dos vas. Cada nodo tiene dos enlaces: uno apunta al nodo anterior, o apunta al valor NULL si es el primer nodo; y otro que apunta al nodo siguiente, o apunta al valor NULL si es el ltimo nodo. En algn lenguaje de muy bajo nivel, XOR-Linking ofrece una va para implementar listas doblemente enlazadas, usando una sola palabra para ambos enlaces, aunque esta tcnica no se suele utilizar.

Listas enlazadas circulares


En una lista enlazada circular, el primer y el ltimo nodo estn unidos juntos. Esto se puede hacer tanto para listas enlazadas simples como para las doblemente enlazadas. Para recorrer una lista enlazada circular podemos empezar por cualquier nodo y seguir la lista en cualquier direccin hasta que se regrese hasta el nodo original. Desde otro punto de vista, las listas enlazadas circulares pueden ser vistas como listas sin comienzo ni fin. Este tipo de listas es el ms usado para dirigir buffers para ingerir datos, y para visitar todos los nodos de una lista a partir de uno dado.

Una lista enlazada circular que contiene tres valores enteros

Listas enlazadas circulares simples


Cada nodo tiene un enlace, similar al de las listas enlazadas simples, excepto que el siguiente nodo del ltimo apunta al primero. Como en una lista enlazada simple, los nuevos nodos pueden ser solo eficientemente insertados despus de uno que ya tengamos referenciado. Por esta razn, es usual quedarse con una referencia solamente al ltimo elemento en una lista enlazada circular simple, esto nos permite rpidas inserciones al principio, y tambin permite accesos al primer nodo desde el puntero del ltimo nodo. 1

Listas enlazadas doblemente circulares


En una lista enlazada doblemente circular, cada nodo tiene dos enlaces, similares a los de la lista doblemente enlazada, excepto que el enlace anterior del primer nodo apunta al ltimo y el enlace siguiente del ltimo nodo, apunta al primero. Como en una lista doblemente enlazada, las inserciones y eliminaciones pueden ser hechas desde cualquier punto con acceso a algn nodo cercano. Aunque estructuralmente una lista circular doblemente enlazada no tiene ni principio ni fin, un puntero de acceso externo puede establecer el nodo apuntado que est en la cabeza o al nodo cola, y as mantener el orden tan bien como en una lista doblemente enlazada.

Nodos centinelas
A veces las listas enlazadas tienen un nodo centinela (tambin llamado falso nodo o nodo ficticio) al principio o al final de la lista, el cual no es usado para guardar datos. Su propsito es simplificar o agilizar algunas operaciones, asegurando que cualquier nodo tiene otro anterior o posterior, y que toda la lista (incluso alguna que no contenga datos) siempre tenga un primer y ltimo nodo.

Aplicaciones de las listas enlazadas


Las listas enlazadas son usadas como mdulos para otras muchas estructuras de datos, tales como pilas, colas y sus variaciones. El campo de datos de un nodo puede ser otra lista enlazada. Mediante este mecanismo, podemos construir muchas estructuras de datos enlazadas con listas; esta prctica tiene su origen en el lenguaje de programacin Lisp, donde las listas enlazadas son una estructura de datos primaria (aunque no la nica), y ahora es una caracterstica comn en el estilo de programacin funcional. A veces, las listas enlazadas son usadas para implementar vectores asociativos, y estas en el contexto de las llamadas listas asociativas. Hay pocas ventajas en este uso de las listas enlazadas; hay mejores formas de implementar stas estructuras, por ejemplo con rboles binarios de bsqueda equilibrados. Sin embargo, a veces una lista enlazada es dinmicamente creada fuera de un subconjunto propio de nodos semejante a un rbol, y son usadas ms eficientemente para recorrer sta serie de datos.

Ventajas
Como muchas opciones en programacin y desarrollo, no existe un nico mtodo correcto para resolver un problema. Una estructura de lista enlazada puede trabajar bien en un caso pero causar problemas en otros. He aqu una lista con algunas de las ventajas ms comunes que implican las estructuras de tipo lista. En general, teniendo una coleccin dinmica donde los elementos estn siendo aadidos y eliminados frecuentemente e importa la localizacin de los nuevos elementos introducidos se incrementa el beneficio de las listas enlazadas.

Lenguajes soportados
Muchos lenguajes de programacin tales como Lisp y Scheme tienen listas enlazadas simples ya construidas. En muchos lenguajes de programacin, estas listas estn construidas por nodos, cada uno llamado cons o celda cons. Las celdas cons tienen dos campos: el car, una referencia del dato al nodo, y el cdr, una referencia al siguiente nodo. Aunque las celdas cons pueden ser usadas para construir otras estructuras de datos, este es su principal objetivo. En lenguajes que soportan tipos abstractos de datos o plantillas, las listas enlazadas ADTs o plantillas estn disponibles para construir listas enlazadas. En otros lenguajes, las listas enlazadas son tpicamente construidas usando referencias junto con el tipo de dato record. En la seccin de implementaciones hay un ejemplo completo en C y en Maude

Almacenamiento interno y externo


Cuando se construye una lista enlazada, nos enfrentamos a la eleccin de si almacenar los datos de la lista directamente en los nodos enlazados de la lista, llamado almacenamiento interno, o simplemente almacenar una referencia al dato, llamado almacenamiento externo. El almacenamiento interno tiene la ventaja de hacer accesos a los datos ms eficientes, requiriendo menos almacenamiento global, teniendo mejor referencia de localidad, y simplifica la gestin de memoria para la lista (los datos son alojados y desalojados al mismo tiempo que los nodos de la lista). El almacenamiento externo, por otro lado, tiene la ventaja de ser ms genrico, en la misma estructura de datos y cdigo mquina puede ser usado para una lista enlazada, no importa cual sea su tamao o los datos. Esto hace que sea ms fcil colocar el mismo dato en mltiples listas enlazadas. Aunque con el almacenamiento interno los mismos datos pueden ser colocados en mltiples listas incluyendo mltiples referencias siguientes en la estructura de datos del nodo, esto podra ser entonces necesario para crear rutinas separadas para aadir o borrar celdas basadas en cada campo. Esto es posible creando listas enlazadas de elementos adicionales que usen almacenamiento interno usando almacenamiento externo, y teniendo las celdas de las listas enlazadas adicionales almacenadas las referencias a los nodos de las listas enlazadas que contienen los datos.

En general, si una serie de estructuras de datos necesita ser incluida en mltiples listas enlazadas, el almacenamiento externo es el mejor enfoque. Si una serie de estructuras de datos necesitan ser incluidas en una sola lista enlazada, entonces el almacenamiento interno es ligeramente mejor, a no ser que un paquete genrico de listas genricas que use almacenamiento externo est disponible. Asimismo, si diferentes series de datos que pueden ser almacenados en la misma estructura de datos son incluidos en una lista enlazada simple, entonces el almacenamiento interno puede ser mejor.

Estructuras de datos relacionadas


Tanto las pilas como las colas son a menudo implementadas usando listas enlazadas, y simplemente restringiendo el tipo de operaciones que son soportadas. La skip list, o lista por saltos, es una lista enlazada aumentada con capas de punteros para saltos rpidos sobre grandes nmeros de elementos, y descendiendo haca la siguiente capa. Este proceso contina hasta llegar a la capa inferior, la cual es la lista actual. Un rbol binario puede ser visto como un tipo de lista enlazada donde los elementos estn enlazados entre ellos mismos de la misma forma. El resultado es que cada nodo puede incluir una referencia al primer nodo de una o dos listas enlazadas, cada cual con su contenido, formando as los subrboles bajo el nodo. Una lista enlazada desenrollada es una lista enlazada cuyos nodos contiene un vector de datos. Esto mejora la ejecucin de la cach, siempre que las listas de elementos estn contiguas en memoria, y reducen la sobrecarga de la memoria, porque necesitas menos metadatos para guardar cada elemento de la lista. Una tabla hash puede usar listas enlazadas para guardar cadenas de tems en la misma posicin de la tabla hash.

Listas doblemente enlazadas


Con estas listas es necesario actualizar muchos ms punteros pero tambin se necesita menos informacin porque podemos usar un puntero para recorrer hacia atrs y consultar elementos. Se crean nuevas operaciones y elimina algunos casos especiales. Aadimos el campo anterior a nuestros nodos, apuntando al elemento anterior, y UltimoNodo a nuestra estructura, el cual siempre apunta al ltimo elemento de la lista. PrimerNodo y UltimoNodo siempre estn a nulo en la lista vaca.

record Node { data // El dato almacenado en el nodo next // Una referencia al nodo siguiente, nulo para el ltimo nodo prev // Una referencia al nodo anterior, nulo para el primer nodo } record List {

Node firstNode lista vaca Node lastNode lista vaca }

// apunta al primer nodo de la lista; nulo para la // apunta al ltimo nodo de la lista; nulo para la

Formas de recorrer la lista: Hacia Delante

node := list.firstNode while node null <do something with node.data> node := node.next

Hacia Atrs

node := list.lastNode while node null <do something with node.data> node := node.prev

Estas funciones simtricas aaden un nodo despus o antes de uno dado:

function insertAfter(List list, Node node, Node newNode) newNode.prev := node newNode.next := node.next if node.next = null node.next := newNode list.lastNode := newNode else node.next.prev := newNode node.next := newNode function insertBefore(List list, Node node, Node newNode) newNode.prev := node.prev newNode.next := node if node.prev is null

node.prev := newNode list.firstNode := newNode else node.prev.next := newNode node.prev := newNode

Tambin necesitamos una funcin para insertar un nodo al comienzo de una lista posiblemente vaca.

function insertBeginning(List list, Node newNode) if list.firstNode = null list.firstNode := newNode list.lastNode := newNode newNode.prev := null newNode.next := null else insertBefore (list, list.firstNode, newNode)

Una funcin simtrica que inserta al final:

function insertEnd(List list, Node newNode) if list.lastNode = null insertBeginning (list, newNode) else insertAfter (list, list.lastNode, newNode)

Borrar un nodo es fcil, solo requiere usar con cuidado firstNode y lastNode.

function remove(List list, Node node) if node.prev = null list.firstNode := node.next else node.prev.next := node.next if node.next = null list.lastNode := node.prev else node.next.prev := node.prev destroy node Listas enlazadas doblemente circulares

Asumiendo que someNodo es algn nodo en una lista no vaca, esta lista presenta el comienzo de una lista con someNode. Hacia Delante

node := someNode do do something with node.value node := node.next while node != someNode

Hacia Atrs

node := someNode do do something with node.value node := node.prev while node := someNode

Esta funcin inserta un nodo en una lista enlazada doblemente circular despus de un elemento dado:

function insertAfter(Node node, Node newNode) newNode.next := node.next newNode.prev := node node.next.prev := newNode node.next := newNode

Para hacer "insertBefore", podemos simplificar "insertAfter (node.prev, newNode)". Insertar un elemento en una lista que puede estar vaca requiere una funcin especial.

function insertEnd(List list, Node node) if list.lastNode = null node.prev := node node.next := node else insertAfter (list.lastNode, node) list.lastNode := node

Para insertar al principio simplificamos "insertAfter (list.lastNode, node)".

function remove(List list, Node node) if node.next = node list.lastNode := null else node.next.prev := node.prev node.prev.next := node.next if node = list.lastNode list.lastNode := node.prev; destroy node

Como una lista doblemente enlazada, "removeAfter" y "removeBefore" puede ser implementada con "remove (list, node.prev)" y "remove (list, node.next)".

Listas enlazadas usando vectores de nodos


Previamente se crea una estructura que contiene los apuntadores:

record Entry { integer next; // ndice de la nueva entrada en el vector integer prev; // entrada previa string name; real balance; }

Y finalmente se declara el vector: integer listHead;

Entry Records[1000];

Implementacin de una lista enlazada en C


Las listas enlazadas son tpicamente construidas usando referencias junto con el tipo de dato record #include <stdio.h> #include <stdlib.h> typedef struct ns { int data; struct ns *next; } node; node *list_add(node **p, int i) { /* for printf */ /* for malloc */

/* algunos compiladores no requieren un casting del valor del retorno para malloc */ node *n = (node *)malloc(sizeof(node)); if (n == NULL) return NULL; n->next = *p; *p = n; n->data = i; return n; } void list_remove(node **p) { /* borrar cabeza*/ if (*p != NULL) { node *n = *p; *p = (*p)->next; free(n); } } node **list_search(node **n, int i) { while (*n != NULL) { if ((*n)->data == i) { return n; } n = &(*n)->next; } return NULL; } void list_print(node *n) { if (n == NULL) { printf("lista esta vaca\n"); } while (n != NULL) { printf("print %p %p %d\n", n, n->next, n->data); n = n->next; } } int main(void) { node *n = NULL; list_add(&n, 0); /* lista: 0 */ list_add(&n, 1); /* lista: 1 0 */ list_add(&n, 2); /* lista: 2 1 0 */

list_add(&n, 3); /* lista: 3 2 1 0 */ list_add(&n, 4); /* lista: 4 3 2 1 0 */ list_print(n); list_remove(&n); list_remove(&n->next); (primera) */ list_remove(&n->next); list_remove(&n); list_print(n); return 0; } /* eliminar segundo nodo del final(0)*/ /* eliminar ultimo nodo (3) */ /* borrar primero(4) */ /* borrar nuevo segundo (2) */

list_remove(list_search(&n, 1)); /* eliminar la celda que contiene el 1

Ejemplos de almacenamiento interno y externo


Suponiendo que queremos crear una lista enlazada de familias y sus miembros. Usando almacenamiento interno, la estructura podra ser como la siguiente:

record member { // miembro de una familia member next string firstName integer age } record family { // // la propia familia family next string lastName string address member members // de la lista de miembros de la familia }

Para mostrar una lista completa de familias y sus miembros usando almacenamiento interno podramos escribir algo como esto:

aFamily := Families // comienzo de la lista de familias while aFamily null { // bucle a travs de la lista de familias print information about family aMember := aFamily.members // coger cabeza de esta lista de miembros de esta familia while aMember null { //bucle para recorrer la lista de miembros

print information about member aMember := aMember.next } aFamily := aFamily.next }

Usando almacenamiento externo, nosotros podramos crear las siguientes estructuras:

record node { // estructura genrica de enlace node next pointer data // puntero genrico del dato al nodo } record member { // estructura de una familia string firstName integer age } record family { // estructura de una familia string lastName string address node members // cabeza de la lista de miembros de esta familia }

Para mostrar una lista completa de familias y sus miembros usando almacenamiento externo, podramos escribir:

famNode := Families // comienzo de la cabeza de una lista de familias while famNode null { // bucle de lista de familias aFamily = (family) famNode.data // extraer familia del nodo print information about family memNode := aFamily.members // coger lista de miembros de familia while memNode null { bucle de lista de miembros aMember := (member) memNode.data // extraer miembro del nodo print information about member memNode := memNode.next } famNode := famNode.next }

You might also like