viernes, 6 de marzo de 2009

ESTRUCTURAS LINEALES

PILAS

Una pila es una lista ordinal o estructura de datos en la que el modo de acceso a sus elementos es de tipo LIFO (del inglés Last In First Out, último en entrar, primero en salir) que permite almacenar y recuperar datos. Se aplica en multitud de ocasiones en informática debido a su simplicidad y ordenación implícita en la propia estructura. Para el manejo de los datos se cuenta con dos operaciones básicas: apilar (push), que coloca un objeto en la pila, y su operación inversa, retirar (o desapilar, pop), que retira el último elemento apilado. En cada momento sólo se tiene acceso a la parte superior de la pila, es decir, al último objeto apilado (denominado TOS, Top of Stack en inglés). La operación retirar permite la obtención de este elemento, que es retirado de la pila permitiendo el acceso al siguiente (apilado con anterioridad), que pasa a ser el nuevo TOS.


En cada momento sólo se tiene acceso a la parte superior de la pila, es decir, al último objeto apilado (denominado TOS, Top of Stack en inglés). La operación retirar permite la obtención de este elemento, que es retirado de la pila permitiendo el acceso al siguiente (apilado con anterioridad), que pasa a ser el nuevo TOS.
Por analogía con objetos cotidianos, una operación apilar equivaldría a colocar un plato sobre una pila de platos, y una operación retirar a retirarlo.
Las pilas suelen emplearse en los siguientes contextos:
Evaluación de expresiones en notacion.
Reconocedores sintácticos de lenguajes independientes del contexto.
Implementación de recursividad.


ESTRUCTURAS LINEALES

Listas (estructura de datos)
Una lista enlazada es una de las estructura 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 (punteros) al nodo anterior y/o posterior. El principal beneficio de las listas enlazadas respecto a los array 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 auto-referenciado porque contienen un puntero o link a otro dato del mismo tipo. Las listas enlazadas permiten inserciones y eliminación 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: Lista Enlazadas Simples, Listas Doblemente Enlazadas, Listas Enlazadas Circulares y Listas Enlazadas Doblemente Circulares.
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 básica 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 vacía, si es el último nodo.



Una lista enlazada simple contiene dos valores: el valor actual del nodo y un enlace al siguiente nodo


Lista Doblemente Enlazada
Un tipo de lista enlazada más sofisticado es la lista doblemente enlazada o lista enlazadas de dos vías. Cada nodo tiene dos enlaces: uno apunta al nodo anterior, o apunta al valor
NULL o a la lista vacía si es el primer nodo; y otro que apunta al siguiente nodo siguiente, o apunta al valor NULL o a la lista vacía si es el último nodo.


Una lista doblemente enlazada contiene tres valores: el valor, el link al nodo siguiente, y el link al anterior


En algún lenguaje de muy bajo nivel, XOR-Linking ofrece una vía para implementar listas doblemente enlazadas, usando una sola palabra para ambos enlaces, aunque el uso de esta técnica no se suele utilizar.

Listas enlazadas circulares
En una lista enlazada circular, el primer y el último nodo están unidos juntos. Esto se puede hacer tanto para listas enlazadas simples como para las doblemente enlazadas. Para recorrer un lista enlazada circular podemos empezar por cualquier nodo y seguir la lista en cualquier dirección 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 más 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 después de uno que ya tengamos referenciado. Por esta razón, es usual quedarse con una referencia solamente al último elemento en una lista enlazada circular simple, esto nos permite rápidas inserciones al principio, y también permite accesos al primer nodo desde el puntero del último nodo.


Lista Enlazada Doblemente Circular
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 algún 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.


Aplicaciones de las listas enlazadas
Las listas enlazadas son usadas como módulos 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 practica tiene su origen en el lenguaje de programación Lisp, donde las listas enlazadas son una estructura de datos primaria (aunque no la única), y ahora es una característica común en el estilo de programación funcional.
A veces, las listas enlazadas son usadas para implementar arrays 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 búsqueda equilibrados. Sin embargo, a veces una lista enlazada es dinámicamente creada fuera de un subconjunto propio de nodos semejante a un árbol, y son usadas más eficientemente para recorrer ésta serie de datos.

A continuacion definimos el codigo en Java de las operaciones eliminar, insertar, recorrer, buscar, vacio, tamaño.


Codigo en Java


public class Lista{


private NodoLista primerNodo;

private NodoLista ultimoNodo;

private String nombre;

//Cadena "lista, utilizada para imprimir"

//Construir lista vacia "como nombre"

public Lista ()

{

this ( "lista" );

}

//construir una lista vacia con un nombre

public Lista(String nombreLista)

{

nombre = nombreLista;

primerNodo = ultimoNodo = null;

}

//insertar objeto al frente de la lista

public synchronized void insertarAlFrente (Object elementoInsertar)

{

if(estaVacia()) //primerNodo y ultimoNodo hacen referencia al mismo objeto

primerNodo = ultimoNodo = new NodoLista (elementoInsertar);

else //primerNodo hace referencia a un nuevo nodo

primerNodo = new NodoLista (elementoInsertar, primerNodo);

}

//insertar objeto al final de la lista

public synchronized void insertarAlFinal (Object elementoInsertar)

{

if (estaVacia()) //primerNodo y ultimoNodo hacen referencia al mismo objeto

primerNodo = ultimoNodo = new NodoLista (elementoInsertar);

else // el objeto siguienteNodo que va despues de ultimoNodo hace referencia a un nuevo Nodo

ultimoNodo = ultimoNodo.siguienteNodo = new NodoLista (elementoInsertar);

}

// eliminar primer nodo de la lista

public synchonized Object eliminarDelFrente () trows ExcepcionListaVacia

{

if (estaVacia()) //lanzar exepcion si la lista esta vacia

throw new ExcepcionListaVacia (nombre);

Object elementoEliminado = primerNodo.datos; //recuperar los datos que se van a eliminar

//actualizar las referencias primerNodo y ultimoNodo

if (primerNodo == ultimoNodo)

primerNodo = ultimoNodo = null;

else

primerNodo = primerNodo.siguienteNOdo;

return elementoEliminado; // devolver datos del nodo eliminado

} //fin del metodo eliminarDelFrente

//eliminar ultimo nodo de la Lista

public synchronized Object eliminarDelFinal() throws ExepcionListaVacia

{

if (estaVacia()) //lanzar excepcion si lista esta vacia

throw new ExcepcionListaVacia (nombre);

Object elementoEliminado = ultimoNodo.datos; // recuperar los datos que se van a eliminar

// actualizar las referencias primerNodo y ultimoNOdo

if (primerNodo == ultimoNodo)

primerNodo = ultimoNodo = null;

else{ //localizar nuevo ultimo nodo

NodoLista actual = primerNodo;

// iterar mientras nodo actual no haga referencia al ultimoNodo

while (actual.siguienteNodo != ultimoNodo)

actual = actual.siguienteNodo;

ultimoNodo = actual; // actual es el nuevo ultimoNodo

actual.siguienteNodo = null;

}

return elementoEliminado; //devolver datos del nodo eliminado

} //fin del metodo eliminarDelFinal

//determinar si la lista esta vacia

public sinchronized boolean estaVacia()

{

return primerNodo == null; //devolver true si la lista esta vacia

}

// mostrar el contenido de la lista

public synchronized void imprimir()

{

if (estaVacia()){

System.out.println (nombre + "vacia");

return;

}

System.out.print("La" + nombre + "es:");

NodoLista actual = primerNodo;

//mientras no se encuentre al final de la lista, imprimir los datos del nodo actual

while (actual !=null) {

System.out.print (actual.datos.toString() + " " );

actual = actual.siguienteNodo;

}

System.out.println ("\n");

}

}