You are on page 1of 32

Republica Bolivariana de Venezuela Ministerio del Poder Popular Para la Defensa Universidad Nacional Experimental Politcnica de la Fuerza Armada

Carpano- Edo. Sucre

Prof: Ing. Raquel vila

Bachiller: Martnez, Oriannys Ing. de sistemas B

Junio del 2012.

Las listas son una estructura de datos de tipo lineal diferencindose de las anteriores en el hecho de que pueden las inserciones y eliminaciones se en cualquier parte de la lista. Esto hace que tengan mayor aplicabilidad en el entorno real. Se abordan los temas relacionados con los conceptos bsicos de las listas, as como tipos de listas y las operaciones que se pueden realizar con las listas, todo conjugado en programas de aplicacin, implementados con apuntadores.

RBOLES

Introduccin Los arboles representan las estructuras no lineales y dinmicas de datos ms importantes en computacin. Dinmicas porque las estructuras de rbol pueden cambiar durante la ejecucin de un programa. No lineales, puesto que a cada elemento del rbol pueden seguirle varios elementos. Los arboles pueden ser construidos con estructuras estticas y dinmicas. Las estticas son arreglos, registros y conjuntos, mientras que las dinmicas estn representadas por listas. Los arboles tienen una gran variedad de aplicaciones. Por ejemplo, se pueden utilizar para representar frmulas matemticas, para organizar adecuadamente la informacin, para construir un rbol genealgico, para el anlisis de circuitos elctricos y para numerar los captulos y secciones de un libro.

rbol Es una estructura de datos ampliamente usada que imita la forma de un rbol (un conjunto de nodos conectados). Raz o nodo padre: El nodo principal del cual salen los hijos. Hijos: Son todos los que descienden de un nodo Padre. Hojas: Es un nodo que no tiene hijos.

rboles generales En un rbol general cada nodo puede poseer un nmero indeterminado de hijos. La implementacin de los nodos en este caso se realiza de la siguiente manera: como no se sabe de antemano cuantos hijos tiene un nodo en particular se utilizan dos referencias, una a su primer hijo y otra a su hermano ms cercano. La raz del rbol necesariamente tiene la referencia a su hermano como null. Un rbol general puede representarse como un rbol binario, con la salvedad que el hijo derecho de la raz es siempre null. Si se permite que la raz del rbol tenga hermanos, lo que se conoce como bosque, entonces se tiene que el conjunto de los bosques generales es isomorfo al conjunto de los rboles binarios. En efecto,

las propiedades vistas en los rboles binarios se siguen cumpliendo en los rboles generales.

Caractersticas Nivel o profundidad de un nodo: Longitud del camino para ir desde la raz al nodo. Por definicin la raz est en el nivel 0. Por ejemplo: profundidad(Y)=2, profundidad(raz)=0, profundidad(rbol)= profundidad(hoja ms profunda).

Altura de un nodo: Longitud del camino ms largo desde el nodo a una hoja. Por ejemplo: Altura(X)=1, Altura(Y)=0, Altura(arbol)=Altura(raz)=profundidad(rbol) Grado de nodo: Cantidad de hijos de un nodo cualquiera. Grado de rbol: Cantidad mxima de hijos posibles de asociar a un nodo del rbol Segn Estructura de Niveles

Arbol completo: Es un rbol binario en el cual cada nodo es una hoja o posee exactamente 2 hijos. Arbol lleno: Es un rbol binario con hojas en a lo ms dos niveles adyacentes l-1 y l, en las cuales los nodos terminales se encuentran ubicados en las posiciones de ms a la izquierda del rbol.

Si un rbol binario es completo, necesariamente es lleno

rbol binario Es una estructura de datos en la cual cada nodo siempre tiene un hijo izquierdo y un hijo derecho. No pueden tener ms de dos hijos (de ah el nombre "binario"). Si algn hijo tiene como referencia a null, es decir que no almacena ningn dato, entonces este es llamado un nodo externo. En el caso contrario el hijo es llamado un nodo interno. Un rbol binario puede declararse de la siguiente manera: typedef struct tarbol{ int clave; struct tarbol *izq, *der; } tarbol;

Recorridos sobre rboles binarios Recorrido en profundidad. Recorrido en preorden Consiste en visitar el nodo actual (visitar puede ser simplemente mostrar la clave del nodo por pantalla), y despus visitar el subrbol izquierdo y una vez visitado, visitar el subrbol derecho. Es un proceso recursivo por naturaleza. void preorden(tarbol *a) { if (a != null) { visitar(a); preorden(a->izq); preorden(a->der); }

Recorrido en inorden se visita el subrbol izquierdo, el nodo actual, y despus se visita el subrbol derecho.

void inorden(tarbol *a) { if (a != null) { inorden(a->izq); visitar(a); inorden(a->der); } } recorrido en postorden Se visitan primero el subrbol izquierdo, despus el subrbol derecho, y por ltimo el nodo actual. void postorden(arbol *a) { if (a != null) { postorden(a->izq); postorden(a->der); visitar(a); }} Recorridos en amplitud

Consiste en ir visitando el rbol por niveles. Primero se visitan los nodos de nivel 1 (la raz), despus los nodos de nivel 2, as hasta que ya no queden ms. Si se hace el recorrido en amplitud del rbol de la figura ejemplo se visitaran los nodos en este orden: En este caso el recorrido no se realizar de forma recursiva sino iterativa, utilizando una cola como estructura de datos auxiliar: el procedimiento consiste en encolar (si no estn vacos) los subrboles izquierdo y derecho del nodo extrado de la cola, y seguir desencolando y encolando hasta que la cola est vaca. En la codificacin que viene a continuacin no se implementan las operaciones sobre colas.

void amplitud(tarbol *a) { tcola cola; /* las claves de la cola sern de tipo rbol binario */ arbol *aux; if (a != null) { crearcola(cola); encolar(cola, a); while (!colavacia(cola)) { desencolar(cola, aux); visitar(aux); if (aux->izq != null) encolar(cola, aux->izq); if (aux->der != null) encolar(cola, aux->der); }}} rbol binario de bsqueda Todo rbol vaco es un rbol binario de bsqueda. Un rbol binario no vaco, de raz R, es un rbol binario de bsqueda si:

En caso de tener subrbol izquierdo, la raz R debe ser mayor que el valor mximo almacenado en el subrbol izquierdo, y que el subrbol izquierdo sea un rbol binario de bsqueda. En caso de tener subrbol derecho, la raz R debe ser menor que el valor mnimo almacenado en el subrbol derecho, y que el subrbol derecho sea un rbol binario de bsqueda. Operaciones bsicas sobre rboles binarios de bsqueda Bsqueda La bsqueda consiste acceder a la raz del rbol, si el elemento a localizar coincide con ste la bsqueda ha concluido con xito, si el elemento es menor se busca en el subrbol izquierdo y si es mayor en el derecho. Si se alcanza un nodo hoja y el elemento no ha sido encontrado se supone que no existe en el rbol.

boolean buscar(tarbol *a, int elem) { if (a == null) return false; else if (a->clave < elem) return buscar(a->der, elem); else if (a->clave > elem) return buscar(a->izq, elem); else return true; } Insercin La insercin es similar a la bsqueda y se puede dar una solucin tanto iterativa como recursiva. Si tenemos inicialmente comoparmetro un rbol vaco se crea un nuevo nodo como nico contenido el elemento a insertar. Si no lo est, se comprueba si el elemento dado es menor que la raz del rbol inicial con lo que se inserta en el subrbol izquierdo y si es mayor se inserta en el subrbol derecho. De esta forma las inserciones se hacen en las hojas.

void insertar(tarbol **a, int elem){ if (*a == null) { *a = (arbol *) malloc(sizeof(arbol));

(*a)->clave = elem; (*a)->izq = (*a)->der = null; } else if ((*a)->clave < elem) insertar(&(*a)->der, elem); else if ((*a)->clave > elem) insertar(&(*a)->izq, elem); }

Borrado La operacin de borrado no es tan sencilla como las de bsqueda e insercin. Existen varios casos a tener en consideracin:

Borrar un nodo sin hijos o nodo hoja: simplemente se borra y se establece a nulo el apuntador de su padre.

Nodo a eliminar 74

Borrar un nodo con un subrbol hijo: se borra el nodo y se asigna su subrbol hijo como subrbol de su padre.

Nodo a eliminar 70

Borrar un nodo con dos subrboles hijo: la solucin est en reemplazar el valor del nodo por el de su predecesor o por el de su sucesor en inorden y posteriormente borrar este nodo. Su predecesor en inorden ser el nodo ms a la derecha de su subrbol izquierdo (mayor nodo del subarbol izquierdo), y su sucesor el nodo ms a la izquierda de su subrbol derecho (menor nodo del

subrbol derecho). En la siguiente figura se muestra cmo existe la posibilidad de realizar cualquiera de ambos reemplazos:

Nodo a eliminar 59.

El siguiente algoritmo en C realiza el borrado en un rbol binario de bsqueda. El procedimiento reemplazar busca la mayor clave del subrbol izquierdo y la asigna al nodo a eliminar. void reemplazar(tArbol **a, tArbol **aux); /*Prototipo de la funcion ''reemplazar''*/ void borrar(tArbol **a, int elem) { tArbol *aux; if (*a == NULL) return; if ((*a)->clave < elem) borrar(&(*a)->hDerecho, elem); else if ((*a)->clave > elem) borrar(&(*a)->hIzquierdo, elem); else if ((*a)->clave == elem) { aux = *a; if ((*a)->hIzquierdo == NULL) *a = (*a)->hDerecho; else if ((*a)->hDerecho == NULL) *a = (*a)->hIzquierdo; else reemplazar(&(*a)->hIzquierdo, &aux); free(aux); } } void reemplazar(tArbol **a, tArbol **aux) { if ((*a)->hDerecho == NULL)

{ (*aux)->clave = (*a)->clave; *aux = *a; *a = (*a)->hIzquierdo; } else reemplazar(&(*a)->hDerecho, aux); }

Listas
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 (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. En las listas existe un nodo especial: el primero. Normalmente diremos que nuestra lista es un puntero a ese primer nodo o 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. El nodo tpico para construir listas tiene esta forma: struct nodo { int dato; struct nodo *siguiente; }; Declaracin de una lista typedef struct _nodo { int dato; struct _nodo *siguiente; } tipoNodo; typedef tipoNodo *pNodo; typedef tipoNodo *Lista;

Tipos de listas
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. -Lista Doblemente Enlazada 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 el uso de 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. -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.

-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 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.

Estructuras de datos 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.

Funciones bsica de las listas


Insercin de un elemento en la lista A continuacin el algoritmo de insercin y registro de los elementos:

declaracin del elemento a insertar asignacin de la memoria para el nuevo elemento rellenar el contenido del campo de datos actualizar los punteros hacia el primer y ltimo elemento si es necesario. Caso particular: en una lista con un solo elemento, el primero es al mismo tiempo el ltimo. Actualizar el tamao de la lista

Para aadir un elemento a la lista hay varios casos:


Insercin en una lista vaca Insercin al inicio de la lista Insercin al final de la lista Insercin en otra parte de la lista.

1. Insercin en una lista vaca Ejemplo de la funcin: int ins_en_lista_vacia (Lista *lista, char *dato); La funcin Etapas:

devuelve

en

caso

de

error,

si

no

devuelve

0.

asignacin de memoria para el nuevo elemento rellenar el campo de datos del nuevo elemento el puntero siguiente del nuevo elemento apuntar hacia NULL (ya que la insercin es hecha en una lista vaca se utiliza la direccin del puntero inicio que vale NULL) los punteros inicio y fin apuntaran hacia el nuevo elemento el tamao es actualizado

La funcin /* insercin en una lista vaca */ int ins_en_lista_vacia (Lista * lista, char *dato){ Element *nuevo_elemento; if ((nuevo_elemento = (Element *) malloc (sizeof (Element))) == NULL) return -1; if ((nuevo _elemento->dato = (char *) malloc (50 * sizeof (char))) == NULL) return -1; strcpy (nuevo_elemento->dato, dato); nuevo_elemento->siguiente = NULL; lista->inicio = nuevo_elemento; lista->fin = nuevo_elemento; lista->tamao++; return 0; } 2. Insercin al inicio de la lista Ejemplo de la funcin: int ins_inicio_lista (Lista *lista,char *dato); La funcin Etapas:

devuelve

-1

en

caso

de

error,

si

no

devuelve

0.

asignacin de memoria al nuevo elemento rellenar el campo de datos del nuevo elemento

el puntero siguiente del nuevo elemento apunta hacia el primer elemento el puntero inicio apunta hacia el nuevo elemento el puntero fin no cambia el tamao es incrementado

La funcin /* insercin al inicio de la lista */ int ins_inicio_lista (Lista * lista, char *dato){ Element *nuevo_elemento; if ((nuevo_elemento = (Element *) malloc (sizeof (Element))) == NULL) return -1; if ((nuevo_elemento->dato = (char *) malloc (50 * sizeof (char))) == NULL) return -1; strcpy (nuevo_elemento->dato, dato); nuevo_elemento->siguiente = lista->inicio lista->inicio = nuevo_elemento; lista->tamao++; return 0; } 3. Insercin al final de la lista

Ejemplo de la funcin: int ins_fin_lista (Lista *lista, Element *actual, char *dato); La funcin Etapas:

devuelve

-1

en

caso

de

error,

si

no

devuelve

0.

asignacin de memoria al nuevo elemento rellenar el campo de datos del nuevo elemento el puntero siguiente del ultimo elemento apunta hacia el nuevo elemento el puntero fin apunta hacia el nuevo elemento el puntero inicio no cambia el tamao es incrementado

La funcin /*insercin al final de la lista */ int ins_fin_lista (Lista * lista, Element * actual, char *dato){ Element *nuevo_elemento; if ((nuevo_elemento = (Element *) malloc (sizeof (Element))) == NULL) return -1; if ((nuevo_elemento->dato = (char *) malloc (50 * sizeof (char))) == NULL) return -1;

strcpy (nuevo_elemento->dato, dato); actual->siguiente = nuevo_elemento; nuevo_elemento->siguiente = NULL; lista->fin = nuevo_elemento; lista->tamao++; return 0; } 4. Insercin en otra parte de la lista Ejemplo de la funcin: int ins_lista (Lista *lista, char *dato,int pos); La funcin devuelve -1 en caso de error, si no devuelve 0. La insercin se efectuar despus de haber pasado a la funcin una posicin como argumento. Si la posicin indicada no tiene que ser el ltimo elemento. En ese caso hay que utilizar la funcin de insercin al final de la lista. Etapas:

asignacin de memoria al nuevo elemento rellenar el campo de datos del nuevo elemento Elegir una posicin en la lista (la insercin se har despus de haber elegido la posicin) el puntero siguiente del nuevo elemento apunta hacia la direccin a la que apunta el puntero siguiente del elemento actual. el puntero siguiente del elemento actual apunta al nuevo elemento los punteros inicio y fin no cambian el tamao se incrementa en una unidad

La funcin /* insercin en la posicin solicitada */ int ins_lista (Lista * lista, char *dato, int pos){ if (lista->tamao < 2) return -1;} if (pos < 1 || pos >= lista->tamao){ return -1; } Element *actual; Element *nuevo_elemento; int i; if ((nuevo_elemento = (Element *) malloc (sizeof (Element))) == NULL){ return -1; }

if ((nuevo_elemento->dato = (char *) malloc (50 * sizeof (char))){ == NULL) return -1;} actual = lista->inicio; for (i = 1; i < pos; ++i){ actual = actual->siguiente; if (actual->siguiente == NULL){ return -1; } strcpy (nuevo_elemento->dato, dato); nuevo_elemento->siguiente = actual->siguiente; actual->siguiente = nuevo_elemento; lista->tamao++; return 0; } C. Eliminacin de un elemento de la lista A continuacin un algoritmo para eliminar un elemento de la lista:

uso de un puntero temporal para guardar la direccin de los elementos a eliminar el elemento a eliminar se encuentra despus del elemento actual

Apuntar el puntero siguiente del elemento actual hacia la direccin del puntero siguiente del elemento a eliminar

liberar la memoria ocupada por el elemento eliminado actualizar el tamao de la lista Eliminacin al inicio de la lista Eliminacin en otra parte de la lista

Para eliminar un elemento de la lista hay varios casos:


1. Eliminacin al inicio de la lista Ejemplo de la funcin: int sup_inicio (Lista *lista);

La funcin Etapas:

devuelve

-1

en

caso

de

error,

si

no

devuelve

0.

el puntero sup_elem contendr la direccin del 1er elemento el puntero inicio apuntara hacia el 2do elemento el tamao de la lista disminuir un elemento

La funcin /* eliminacin al inicio de la lista */ int sup_inicio (Lista * lista){ if (lista->tamao == 0) return -1; Element *sup_elemento; sup_element = lista->inicio; lista->inicio = lista->inicio->siguiente; if (lista->tamao == 1) lista->fin = NULL; free (sup_elemento->dato); free (sup_elemento); lista->tamao--;

return 0; } 2. Eliminacin en otra parte de la lista Ejemplo de la funcin: int sup_en_lista (Lista *lista, int pos); La funcin Etapas:

devuelve

-1

en

caso

de

error, hacia

si la

no

devuelve apunta

0. el

el puntero sup_elem contendr la direccin puntero siguiente del elemento actual

que

el puntero siguiente del elemento actual apuntara hacia el elemento al que apunta el puntero siguiente del elemento que sigue al elemento actual en la lista.

Si el elemento actual es el penltimo elemento, el puntero fin debe ser actualizado.

el tamao de la lista ser disminuido en un elemento

La funcin /* eliminar un elemento despus de la posicin solicitada */ int sup_en_lista (Lista * lista, int pos){ if (lista->tamao = lista->tamao) return -1; int i; Element *actual; Element *sup_elemento; actual = lista->inicio; for (i = 1; i < pos; ++i) actual = actual->siguiente; sup_elemento = actual->siguiente; actual->siguiente = actual->siguiente->siguiente; if(actual->siguiente == NULL) lista->fin = actual; free (sup_elemento->dato); free (sup_elemento); lista->tamao--; return 0; }

D. Mostrar la lista Para mostrar la lista entera hay que posicionarse al inicio de la lista (el puntero inicio lo permitir). Luego utilizando el puntero siguiente de cada elemento la lista es recorrida del 1ero al ltimo elemento. La condicin para detener es dada por el puntero siguiente del ltimo elemento que vale NULL. La funcin /* visualizacin de la lista */ void visualizacin (Lista * lista){ Element *actual; actual = lista->inicio; while (actual != NULL){ printf ("%p - %s\n", actual, actual->dato); actual = actual->siguiente; } } Representacin grafica de las listas enlazadas

Memoria dinmica Es la memoria que se reserva en tiempo de ejecucin, permitiendo reservar ms o liberar la que ya no est siendo usada. El C estndar proporciona una serie de funciones de librera que nos permiten gestionar la memoria de una forma dinmica. Las ms importantes son:

Malloc Free Ambas contenidas en el include malloc.h. Junto con estas funciones sizeof es de gran importancia, ya que malloc se emplea para reservar memoria sin atender al tipo sino al tamao. Como no sabemos en que posicin estar la memoria hasta que la pedimos mediante malloc, la memoria dinmica se gestiona mediante el uso de punteros.

Malloc
#include<malloc.h> void * malloc(size_t size); La funcin solo requiere de un parmetro, que es el tamao de memoria a reservar. La funcin devolver un puntero a void que deberemos convertir mediante cast* al tipo de dato que hayamos reservado. En caso de error, malloc devolver NULL (un puntero a void con valor 0). int *a; /* pedimos memoria para un entero */ a=(int *)malloc(sizeof(int)); if(a==NULL) puts(.Error al reservar memoria.); Reservar memoria para un vector es sencillo, si recordamos que un vector es una serie de elementos consecutivos en memoria a los cuales accedemos con un puntero al primer elemento. int *v; /* pedimos memoria para un vector de enteros con tamao 10 */ /* dicindole a malloc que queremos el tamao de: 1 entero por 10 */ v=(int *)malloc(sizeof(int)*10); if(v==NULL) puts(.Error al reservar memoria.); v[2]=5; /* accedemos al 3er elemento como si fuera memoria esttica */

Free
#include<malloc.h> void free(void *ptr);

La funcin solo requiere de un parmetro, que es el puntero a la memoria a liberar. Si el puntero es NULL, nada ocurre. Emplearemos free para liberar memoria reservada con malloc. int *a; /* pedimos memoria para un entero */ a=(int *)malloc(sizeof(int)); if(a==NULL) puts(.Error al reservar memoria.); ... free(a); /* ahora la memoria apuntada por a no est disponible */ (*a)=10; /* puede ocasionar un error, ya que la memoria ya no est */ /* disponible pero el puntero aun apunta a ella */ a=NULL; /* es un buen hbito que los punteros apunten a NULL cuando */ /* no apunten a memoria, as podemos comprobar si no contienen */ /* Memoria comparando con NULL antes de usarlos */

Listas y vectores Las listas enlazadas tienen las siguientes ventajas sobre los arrays:

No requieren memoria extra para soportar la expansin. Por el contrario, los arrays requieren memoria extra si se necesita expandirlo (una vez que todos los elementos tienen datos no se pueden aadir datos nuevos a un array). Ofrecen una insercin/borrado de elementos ms rpida que sus operaciones equivalentes en los arrays. Slo se tienen que actualizar los enlaces despus de identificar la posicin de insercin/borrado. Desde la perspectiva de los arrays, la insercin de datos requiere el movimiento de todos los otros datos del array para crear un elemento vaco. De forma similar, el borrado de un dato existente requiere el movimiento de todos los otros datos para eliminar el elementovaco.

En contraste, los arrays ofrecen las siguientes ventajas sobre las listas enlazadas:

Los elementos de los arrays ocupan menos memoria que los nodos porque no requieren campos de enlace. Los arrays ofrecen un acceso ms rpido a los datos, mediante ndices basados en enteros.

Las listas enlazadas son ms apropiadas cuando se trabaja con datos dinmicos. En otras palabras, inserciones y borrados con frecuencia. Por el contrario, los arrays son ms apropiados cuando los datos son estticos (las inserciones y borrados son raras). De todas formas, no olvide que si se queda sin espacio cuando aade tems a un array, debe crear un array ms grande, copiar los datos del array original el nuevo array mayor y eliminar el original. Esto cuesta tiempo, lo que afecta especialmente al rendimiento si se hace repetidamente. Mezclando una lista de enlace simple con un array uni-dimensional para acceder a los nodos mediante los ndices del array no se consigue nada. Gastar ms memoria, porque necesitar los elementos del array ms los nodos, y tiempo, porque necesitar mover los tems del array siempre que inserte o borre un nodo. Sin embargo, si es posible integrar el array con una lista enlazada para crear una estructura de datos til.

Ejemplo de lista #include<stdio.h> #include<conio.h> #include<listas.h> Void inicialisacion (Lista * lista){ lista ->inicio = NULL; lista ->fin = NULL; lista ->tamao = 0; } /* insercion en une lista vacia */ int ins_en_lista _vacia (Lista * lista, char *dato){ Elemento *nuevo_elemento; if ((nuevo_elemento = (Elemento *) malloc (sizeof (Elemento))) == NULL) return -1; if ((nuevo_elemento->dato = (char *) malloc (50 * sizeof (char))) == NULL)

return -1; strcpy (nuevo_elemento->dato, dato); nuevo_elemento->siguiente = NULL; lista ->inicio = nuevo_elemento; lista ->fin = nuevo_elemento; lista ->tamao++; return 0; } /* insercin al inicio de la lista */ int ins_inicio_lista (Lista * lista, char *dato){ Elemento *nuevo_elemento; if ((nuevo_elemento = (Elemento *) malloc (sizeof (Elemento))) == NULL) return -1; if ((nuevo_elemento->dato = (char *) malloc (50 * sizeof (char))) == NULL) return -1; strcpy (nuevo_elemento->dato, dato); nuevo_elemento->siguiente = lista->inicio; lista ->inicio = nuevo_elemento; lista ->tamao++; return 0; } /*insercion al final de la lista */ int ins_fin_lista (Lista * lista, elemento * actual, char *dato){ Elemento *nuevo_elemento; if ((nuevo_elemento = (Elemento *) malloc (sizeof (Elemento))) == NULL) return -1; if ((nuevo_elemento->dato = (char *) malloc (50 * sizeof (char))) == NULL) return -1; strcpy (nuevo_elemento->dato, dato); actual->siguiente = nuevo_elemento;

nuevo_elemento->siguiente = NULL; lista ->fin = nuevo_elemento; lista ->tamao++; return 0; } /* insercion en la posicion solicitada */ int ins_ lista (Lista * lista, char *dato, int pos){ if (lista ->tamao < 2) return -1; if (pos < 1 || pos >= lista ->tamao) return -1; Elemento *actual; Elemento *nuevo_elemento; int i; if ((nuevo_elemento = (Elemento *) malloc (sizeof (Elemento))) == NULL) return -1; if ((nuevo_elemento->dato = (char *) malloc (50 * sizeof (char))) == NULL) return -1; actual = lista ->inicio; for (i = 1; i < pos; ++i) actual = actual->siguiente; if (actual->siguiente == NULL) return -1; strcpy (nuevo_elemento->dato, dato); nuevo_elemento->siguiente = actual->siguiente; actual->siguiente = nuevo_elemento; lista ->tamao++; return 0; } /* supresin al inicio de la lista */ int sup_inicio (Lista * lista){

if (lista ->tamao == 0) return -1; Elemento *sup_elemento; sup_elemento = lista ->inicio; lista ->inicio = lista ->inicio->siguiente; if (lista ->tamao == 1) lista ->fin = NULL; free (sup_elemento->dato); free (sup_elemento); lista ->tamao--; return 0; } /* suprimir un elemento despus de la posicin solicitada */ int sup_en_lista (Lista * lista, int pos){ if (lista ->tamao = lista ->tamao) return -1; int i; Elemento *actual; Elemento *sup_elemento; actual = lista ->inicio; for (i = 1; i < pos; ++i) actual = actual->siguiente; sup_elemento = actual->siguiente; actual->siguiente = actual->siguiente->siguiente; if(actual->siguiente == NULL) lista ->fin = actual; free (sup_elemento->dato); free (sup_elemento); lista ->tamao--; return 0; } /* visualizacin de la Lista */

void muestra (Lista * lista){ Elemento *actual; actual = lista ->inicio; while (actual != NULL){ printf ("%p - %s\n", actual, actual->dato); actual = actual->siguiente; } } /* destruir la Lista */ void destruir (Lista * Lista){ while (lista ->tamao > 0) sup_inicio (lista); } int menu (Lista *lista,int *k){ int eleccin; printf("********** MENU **********\n"); if (lista ->tamao == 0){ printf ("1. Adicin del1er elemento\n"); printf ("2. Quitar\n"); }else if(lista ->tamao == 1 || *k == 1){ printf ("1. Adicin al inicio de la lista\n"); printf ("2. Adicin al final de la lista\n"); printf ("4. Supresin al inicio de la lista\n"); printf ("6. Destruir la lista\n"); printf ("7. Quitar\n"); }else { printf ("1. Adicin al inicio de la lista\n"); printf ("2. Adicin al final de la lista\n"); printf ("3. Adicin despus de la posicin indicada\n"); printf ("4. Supresin al inicio de la lista\n"); printf ("5. Supresin despus de la posicin indicada\n"); printf ("6. Destruir la lista\n");

printf ("7. Quitar\n"); } printf ("\n\nElegir: "); scanf ("%d", &eleccin); if(lista->tamao == 0 && eleccin == 2) eleccin = 7; return eleccin; getch(); }

You might also like