Listas Circulares

Share Embed Donate


Short Description

Download Listas Circulares...

Description

Instituto Politécnico Nacional Escuela Superior de Ingeniería Mecánica y Eléctrica Unidad Zacatenco

“Estructura y Base de Datos” Profra.: Lic. Cortes Hernández Lilia “LISTAS CIRCULARES”

Grupo 3C4V  PRESENTAN:

Domínguez Lozano Rubén Bárcenas Martínez Bernardo Martínez Cedillo Marco Antonio

Página 1

*ÍNDICE Desarrollo del tema................................ tema....................................................... .............................................. ......................................3 ...............3 Operaciones Operaciones con listas circulares........................ circulares............................................... .............................................. .........................4 ..4 Inserción de una lista vacía............................ vacía................................................... .............................................. ..............................5 .......5 Inserción de una lista no vacía.................................................. vacía......................................................................... ..........................6 ...6 Eliminación Eliminación al inicio de una lista........................... lista.................................................. .............................................8 ......................8 Mostrar lista............................. lista.................................................... .............................................. .............................................. ............................11 .....11 Destrucción Destrucción de una lista............................. lista.................................................... .............................................. ................................12 .........12 *Ejemplos  Números al azar................................... azar.......................................................... .............................................. ......................................13 ...............13 Búsqueda.......................... Búsqueda................................................. .............................................. .............................................. ..................................19 ...........19 Inserción de un elemento al principio de la lista......................................... lista..............................................20 .....20 Manual Técnico y de Usuario................................ Usuario....................................................... ...........................................23 ....................23

BIBLIOGRAFÍA Programación en C Autores: Luis Joyanes Aguilar y Andres Castillo Sanz Ed. Mc Graw Hill Primera edición

Aprenda C en 21 dias Autor: Lucas Sanchez Garcia Ed. Adison Wensly Tercera edición

Página 2

*Desarrollo del Tema  Listas Circulares

La lista circular es una especie de lista enlazada simple o doblemente enlazada, pero que  posee una característica adicional para el desplazamiento dentro de la lista, “ésta no tiene,fin”. Para que la lista sea sin fin, el puntero siguiente del último elemento apuntará hacia el 1er elemento de la lista en lugar de apuntar al valor NULL, como hemos visto en el caso de listas enlazadas simples o doblemente enlazadas En las listas circulares, nunca se llega a una posición en la que ya no sea posible desplazarse. Cuando se llegue al último elemento, el desplazamiento volverá a comenzar desde el  primer elemento. elemento.

 III. La construcción del modelo de un elemento de la lista

Para definir un elemento de la lista, el tipo  struct  será será uti utili liza zado. do. El element ento de la lista sta cont ontendrá ndrá un cam campo dat dato y un punt untero ero sig siguie uiente. nte. El puntero siguiente siguiente debe ser del mismo mismo tipo que el element elemento, o, en caso contrario contrario no  podrá apuntar a elemento siguiente. El puntero siguiente permitirá el acceso hacia el próximo elemento. typedef struct ElementoLista { char *dato; struct ElementoLista *siguiente; }Elemento;

Página 3

Para tener el control de l alista es preferible guardar ciertos elementos: el primer  elemento, el último elemento, el número de elementos. Para Para ello, ello, otra otra estruc estructu tura ra será será util utiliza izada da (no es obl obliga igato torio rio,, pueden pueden ser ser uti utili lizad zadas as variables) typedef struct ListaIdentificar { Elemento *inicio; Elemento *fin; int tamaño; }Lista;

El punt punter eroo inic inicio io cont conten endr dráá la dire direcc cció iónn del del prim primer er elem elemen ento to de la li list sta. a. El punt punteero fin cont ontendr endráá la dire direccció ción del ultimo elemen mento de la lista sta. La variable contiene el número de elementos. tamaño Cualquiera que sea la posición en la lista, los punteros inicio y fin siempre apuntaran hacia el 1er y el último elemento respectivamente. El campo tamaño contendrá el número de elementos de la lista cualquiera sea la operación efectuada sobre la lista.

 IV. Operaciones sobre las listas circulares circulares A. Inicialización Modelo de la función

void inicialización (Lista *lista); Esta Esta operac operació iónn debe debe ser hecha hecha antes antes de cualqu cualquie ierr otra otra operac operación ión sobre sobre la li lista sta.. Inicializa el puntero inicio y el puntero fin con el puntero NULL, y el tamaño con el valor 0.  La función:

void inicialización (Lista *lista){ lista->inicio = NULL; lista->fin = NULL; tamaño = 0; }

Página 4

B. Inserción de un elemento en la lista A continuación el algoritmo de inserción y registro de los elementos: declaración del elemento a insertar  asignación de la memoria para el nuevo elemento rellenar el contenido del campo de datos actualizar los punteros hacia el 1er y ultimo elemento si es necesario. Caso particular: en una lista con un solo elemento, el 1er elemento es al o mismo tiempo el ultimo. •







Actualizar el tamaño de la lista. 1. Inserción en una lista vacía Modelo de la función:

int ins_lista_circ_vacia(Lista * lista, char *dato); La

función

devuelve

-1

en

caso

de

error,

si

no

devuelve

0.

Etapas: asignación de memoria para el nuevo elemento rellenar el campo de datos del nuevo elemento el puntero siguiente del nuevo elemento apuntará hacia si mismo ( es la etapa que vuelve a la lista circular ) los punteros inicio y fin apuntaran hacia el nuevo elemento el tamaño es actualizado











Página 5

 La función:

/* inserción en una lista vacía */ int ins_lista_circ_vacia(Lista * lista, char *dato){ Elemento *nuevo_elemento; if ((nuevo_elemento = (Elemento *) malloc (sizeof ( sizeof (Elemento))) (Elemento))) == NULL) return -1; if ((nuevo_elemento->dato ((nuevo_elemento->dato = (char *) malloc (50 * sizeof (char))) == NULL) return -1; strcpy (nuevo_elemento->dato, dato); nuevo_elemento->siguiente = nuevo_elemento; lista->inicio = nuevo_elemento; lista->fin = nuevo_elemento; lista->tamaño++; return 0; }

2. Inserción en una lista no vacía Modelo de la función:

int ins_lista_circ(Lista * lista, Elemento *actual, char *dato);

La

función

devuelve

-1

en

caso

de

error,

si

no

devuelve

0.

Etapas: asignación de memoria para el nuevo elemento rellenar el campo de datos del nuevo elemento el puntero puntero siguient siguientee del nuevo nuevo element elementoo apunta apunta hacia hacia la direcció direcciónn del primer  elemento (conservar la lista circular) el puntero inicio no cambia el puntero fin apunta hacia el nuevo elemento el tamaño se incrementa en una unidad













Página 6

 La función:

/* inserción en una lista no vacía */ int ins_lista_circ(Lista * lista, Elemento *actual, char *dato){ Elemento *nuevo_elemento; if ((nuevo_elemento = (Elemento *) malloc (sizeof ( sizeof (Elemento))) (Elemento))) == NULL) return -1; if ((nuevo_elemento->dato ((nuevo_elemento->dato = (char *) malloc (50 * sizeof (char))) == NULL) return -1; strcpy (nuevo_elemento->dato, dato); if(actual != lista->fin) return -1; nuevo_elemento->siguiente = actual->siguiente; actual->siguiente = nuevo_elemento; lista->fin = nuevo_elemento; lista->tamaño++; Return 0; }

Página 7

C. Eliminación de un elemento en la lista A continuación el algoritmo de eliminación de un elemento de la lista: uso de un puntero temporal para guardar la dirección de los elementos a eliminar  el elemento a eliminar se encuentra después del elemento actual





Hacer apuntar el puntero siguiente del elemento actual hacia la dirección del puntero siguiente del elemento a eliminar  liberar la memoria ocupada por el elemento eliminado actualizar el tamaño de la lista





Para eliminar un elemento de la lista hay varias situaciones: 1. Eliminación dentro de la lista 2. Eliminación del último elemento de la lista





1. Eliminación al inicio de la lista Modelo de la función:

int sup_list_circ(Lista *lista);

La

función

devuelve

-1

en

caso

de

error,

si

no

devuelve

0.

Etapas: el puntero sup_elemento contendrá la dirección del 1er elemento el puntero inicio apuntara hacia el 2do elemento el puntero siguiente del ultimo elemento apuntara hacia el 1er elemento elemento ( que era el 2do antes de la eliminación ) el tamaño de la lista disminuirá 1 elemento.









Página 8

 La función:

/* eliminación al inicio de la lista */ int sup_lista_circ(Lista * lista){ if (lista->tamaño < 2) return -1; Elemento *sup_element; sup_elemento = lista->inicio; lista->inicio = lista->inicio->siguiente; lista->fin->siguiente = lista->inicio; free (sup_elemento->dato); (sup_elemento->dato); free (sup_elemento); (sup_elemento); lista->tamaño--; return 0; } 2. Eliminación en una lista con un solo elemento Modelo de la función:

int sup_list_circ_unica(Lista *lista);

Página 9

La

función

devuelve

-1

en

caso

de

error,

si

no

devuelve

0.

Etapas: el puntero sup_elemento contendrá la dirección del elemento (la lista contiene un solo elemento) el puntero inicio apuntara hacia NULL el puntero fin apuntara hacia NULL el tamaño de la lista disminuirá un elemento. •







 La función:

/* eliminación en una lista con un solo elemento*/ int sup_lista_circ_unica(Lista *lista){ if (lista->tamaño != 1) return -1; Elemento *sup_elemento; sup_elemento = lista->inicio; lista->inicio = NULL; lista->fin = NULL; free (sup_elemento->dato); (sup_elemento->dato);

Página 10

free (sup_elemento); (sup_elemento); lista->tamaño--; return 0; }

 D. Mostrar la lista

Para mostrar la lista completa, es necesario posicionarse al inicio de la lista (el puntero inicio lo permitirá). Luego, utilizando el puntero siguiente de cada elemento, la lista es recorrida del 1er al ultimo elemento. En comparación con las listas simples y doblemente enlazadas, en el que la condición  para detenerse esta dada por el puntero siguiente del ultimo elemento, que vale NULL,   par paraa la li list staa circ circul ular ar,, no hay hay punt puntoo de dete detenc nció ión, n, a meno menoss que que elij elijam amos os uno. uno. A continuación dos variantes de visualización: •



Mostrar la lista (del 1er al último elemento) Mostrar la lista sin una condición para detenerse.



1. Mostrar la lista (del 1er al a l último elemento)

Uti Utilizare zaremo moss el tama amaño de la lista sta como la condi ondicción para det deteners nersee. La función: /* mostrar la lista */ void mostrar (Lista * lista){ Elemento *actual; actual = lista->inicio; int i; for(i=0;itamaño;++i){ printf ("%p - %s\n", actual, actual->dato); actual = actual->siguiente; } } 2. Mostrar la lista sin una condición para detenerse (indefinidamente) La función: /* recorrer la lista indefinidamente*/

Página 11

void mostrar_indefinidamente mostrar_indefinidamente (Lista * lista){ Elemento *actual; actual = lista->inicio; while (1){ printf ("%p - %s\n", actual, actual->dato); actual = actual->siguiente; } }

E. Destrucción de la lista Para destruir la lista completa, he utilizado al eliminación al inicio de la lista ya que el tamaño es mayor a 1, luego la eliminación en una lista con un solo elemento. La función: /* destruir la lista */ void destruir (Lista * lista){ while (lista->tamaño > 0){ if (lista->tamaño > 1) sup_lista_circ (lista); else sup_lista_circ_unica(lista); }

Página 12

*Ejemplos  Programa Numeros al Azar: (ejemplo1.exe)

En este programa se escriben las declaraciones declaraciones y funciones necesarias necesarias para trabajar en una lista circular.

Análisis del problema: El prog progra rama ma se estr estruc uctu tura ra de la sigu siguie ient ntee form forma: a:.P .Pri rime mera rame ment ntee se hace hacenn las las declaraciones necesarias para tratar la Lista Circular.El programa principal se encarga de realizar las llamadas correspondientes.VaciaLc. Es una función que crea una lista circular vacía..EsVaciaLc. vacía..EsVaciaLc. Es una función que da verdadero cuando la lista circular esta vacía..NuevoNodoLc. Es una función que devuelve un puntero a un nuevo nodo en el que se ha almacenado el dato x..InsertaListaCircular. Realiza la inserción de una lista circular del valor dato. Lo hace teniendo en cuenta que primero es un puntero que apunta al último elemento que se añadió a la lista. Lo que hace es insertar un nuevo nodo en la Lista Lista Circular Circular como como último último elemento, elemento, para para lo cual cual aparte de reali realizar zar los correspondientes correspondientes enlaces, mueve el puntero puntero primero para que apunte siempre al último elemento que se añadió. añadió. De esta forma el primer elemento elemento de la lista siempre siempre estará en el nodo Primero->sig..GeneraPorElFinalLc. Crea una lista circular de números enteros aleatorios, realizando las inserciones con la función InsertaListaCircular. .EscribeListaLc. Se encarga de eliminar el primer nodo de la lista circular que como sabemos estará siempre en Primero->sig. Solo hay que tener en cuenta que si la lista esta vacía vacía no se puede borrar. Si tiene tiene un solo dato dato la lista lista se quedara vacía y habrá que liberar memoria. memoria. Si tiene más de un dato dato habrá que mover el puntero puntero Primero->sig a Primero->sig->sig; y liberar la memoria del nodo que hemos puenteado. .Elimina .EliminarLc. rLc. Se encarga encarga de buscar buscar la primera aparición aparición de dato y borrarla de la lista circular. Lo hace de la siguiente forma. Si la lista esta vacía no hay nada que hacer. En otro caso con una variable lógica enc y con un puntero ptr realiza la búsqueda del dato, controlando no realizar un bucle infinito. Una vez encontrado el elementó se realiza el  borrado teniendo en cuenta: si la lista contiene un solo valor se quedará vacía; si el nodo a borrar por Primero, habrá que mover este puntero; en otro caso no habrá que moverlo. Siempre que se borre un nodo habrá que puentearlo.

Página 13

#include #include #include #define MX 100 #include

typedef int Item; typedef struct NuevoNodo { Item el; struct NuevoNodo*sig; }NodoLc;

void VaciaLc(NodoLc**Primero); int EsVaciaLc(NodoLc *Primero); NodoLc* NuevoNodoLc(Item x); void InsertaListaCircular(NodoLc **Primero, Item datos); void GeneraPorElFinalLc(NodoLc **Primero); void EscribeListaLc(NodoLc *Primero); void EliminarPrimeroLc(NodoLc **Primero);

void main (void) { //clrscr(); NodoLc *Primero; GeneraPorElFinalLc(&Primero); EscribeListaLc(Primero); getch();

Página 14

}

void VaciaLc(NodoLc**Primero) { *Primero=NULL; } int EsVaciaLc(NodoLc *Primero) { return (Primero==NULL); } NodoLc*NuevoNodoLc(Item x) { NodoLc *nn; nn=(NodoLc*)malloc(sizeof(NodoLc)); nn-> el = x; nn-> sig=nn; return nn; }

void InsertaListaCircular (NodoLc **Primero,Item dato) { NodoLc* nn; nn=NuevoNodoLc(dato); if (*Primero!=NULL) { //nn->sig= *Lc ->sig; (*Primero) ->sig=nn; } *Primero = nn; }

Página 15

void GeneraPorElFinalLc(NodoLc **Primero) { Item d; NodoLc *p; p=NULL; randomize(); for (d=random(MX); d; ) {

InsertaListaCircular (&p,d); d= random (MX); } *Primero=p; }

void EscribeListaLc(NodoLc *Primero) { NodoLc *ptr; int k=0; ptr= Primero; if(ptr!=NULL) { ptr=ptr->sig; do { k++; if(k%10==0) { printf("\n"); printf("%d",ptr->el);

Página 16

} else { printf(" "); printf("%d",ptr->el); } ptr=ptr->sig; } while (ptr!=Primero->sig); } } void EliminaPrimeroLc(NodoLc **Primero) { NodoLc *ptr, *p; ptr=*Primero; if(ptr!=NULL) { p=ptr->sig; //p

hay que borrarlo

if (p==ptr) *Primero=NULL; else ptr->sig=p->sig; free(p); } } void EliminarLc (NodoLc** Primero,Item dato) { NodoLc *ptr,*p; int enc = 0;

Página 17

ptr = *Primero; if (ptr==NULL) return; //busqueda mientras no encontrado y no de la vuelta while ((ptr->sig!=*Primero)&&(!enc)) { enc=(ptr->sig->el==dato); if (!enc) ptr = ptr->sig; }enc = (ptr->sig->el==dato); //aqui se debe encontrar el dato if (enc) {p=ptr->sig; if(*Primero==(*Primero)->sig) //solo hay un dato *Primero=NULL; else { if (p==*Primero) *Primero= ptr; ptr->sig=p->sig; } free(p); }

 Ejecutado

Página 18

 Programa: Búsqueda (lista cir.exe)

Definición: La Búsqueda su objetivo es encontrar un dato en el arreglo Info, si lo encuentra lo desplegara en la pantalla, si no lo encuentra no desplegara nada ya que el dato no se encuentra en el arreglo Info. Programa:

#include #include int Busqueda(int Info[8],int Indice[8],int Inicio,int Disp,int Elemento); void main() { int Info[8]={0,10,0,9,5,3,0,20}; int Indice[8]={5,7,6,1,0,3,-999,4}; int Inicio=0,Disp=2,Elemento,Res; coutElemento; Res=Busqueda(Info,Indice,Inicio,Disp,Elemento); if(Res==-999) cout
View more...

Comments

Copyright ©2017 KUPDF Inc.
SUPPORT KUPDF