Вы находитесь на странице: 1из 20

Listas circulares.

En las listas lineales simples o dobles siempre hay un primer nodo y un ltimo nodo que tiene el campo de enlace a nulo. Esto, porque se delimita el comienzo y el trmino de la misma. Una lista circular, por su naturaleza cclica, no tiene ni principio ni fin. No obstante, es til y recomendable establecer un nodo de referencia a partir del cual se acceda a la lista y as poder conocer la posicin inicial y acceder a sus operaciones insertar, borrar etc.

Listas circulares.
Listas enlazadas circulares En una lista enlazada circular, los nodos ltimo y primero estn unidos por un enlace (no apuntan a NULL). Esto es posible tanto para listas enlazadas simples como para las doblemente enlazadas. Para recorrer un lista enlazada circular se puede comenzar por cualquier nodo y seguir la lista en cualquier direccin hasta que se regrese hasta el nodo original. Las listas enlazadas circulares pueden ser vistas como listas sin comienzo ni fin si no hay un punto que lo indique. 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 circulares.

Listas circulares.
Listas enlazadas circulares simples Cada nodo tiene un enlace, anlogo al de las listas enlazadas simples, la diferencia est en 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 (recordemos que aqu no hay inicio ni fin). Lo usual es 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.

Listas circulares.
Lista Doblemente Enlazada Circular En una lista circular doblemente enlazada, cada nodo tiene dos enlaces, anlogamente a la lista doblemente enlazada lineal, el cambio radica en 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 contiguo. Aunque estructuralmente una lista circular doblemente enlazada no tiene ni principio ni fin, un puntero de acceso externo (centinela) puede establecer el nodo apuntado que est en la cabeza o al nodo final, y as mantener el orden como en una lista doblemente enlazada.

Listas circulares.
Nodos Centinelas o cabecera (header nodes) La bsqueda y los algoritmos de ordenacin se simplifican si se usan los llamados Nodos Centinelas o cabecera, donde cada elemento apunta a otro elemento y nunca a nulo. El Nodo Centinela o Puntero Cabeza contiene, como otro, un puntero siguiente que apunta al que se considera como primer elemento de la lista . Tambin contiene un puntero previo que hace lo mismo con el ltimo elemento. El Nodo Centinela es definido como otro nodo en una lista doblemente enlazada. Si los punteros anterior y siguiente apuntan al Nodo Centinela la lista se considera vaca. En otro caso, si a la lista se le aaden elementos ambos puntero apuntarn a otros nodos. Estos Nodos Centinelas simplifican muchos las operaciones pero hay que asegurarse de que los punteros anterior y siguiente existen en cada momento. Como ventaja eliminan la necesidad de guardar la referencia al puntero del principio de la lista y la posibilidad de asignaciones accidentales. Por el contrario, usan demasiado almacenamiento extra y resultan complicados en algunas operaciones.

Listas circulares.
Insercin de un elemento en una lista circular El algoritmo empleado para aadir o insertar un elemento en una lista circular varia dependiendo de la posicin en que se desea insertar el

elemento que inserta el nodo en la lista circular. En todo caso hay que seguir los siguientes pasos: Asignar memoria a nuevo nodo nuevo y almacenar el dato. Si la lista esta vaca, enlazar el campo sig del nuevo nodo nuevo con el propio nuevo nodo, nuevo y poner el puntero de la lista circular en el nuevo nodo nuevo. Si la lista no esta vaca se debe decidir el lugar donde colocar el nuevo nodo nuevo, quedndose con la direccin del nodo inmediatamente anterior ant. Enlazar el campo sig del nuevo nodo nuevo con el campo sig del nodo anterior ant. Enlazar el campo sig del nodo anterior ant con el nuevo nodo nuevo. Si se pretende que el nuevo nodo nuevo ya insertado sea el primero de la lista circular, mover el puntero de la lista circular al nuevo nodo nuevo. En otro caso no hacer nada.

Listas circulares.
Ejemplo 1. Insercin en la lista circular nuevo = (Nodo*) malloc (sizeof(Nodo)); nuevo->dato = el; if (primero==NULL) { nuevo->sig = nuevo; primero = nuevo; } else { nuevo->sig = antanterior->sig; anterior->sig = nuevo; }

Listas circulares.
Eliminacin de un elemento en una lista circular El algoritmo para eliminar un nodo de una lista circular es el siguiente:

Buscar el nodo que contiene el dato quedndose con el nodo anterior ant. Se enlaza el campo sig del nodo anterior ant con el campo siguiente sig del nodo a borrar. Si la lista contena un solo nodo se pone a NULL la lista. En caso de que el nodo a eliminar sea el referenciado por el puntero de acceso a la lista, Lc y contenga mas de un nodo se modifica Lc para que tenga la direccin del nodo anterior ant o bien el campo sig de Lc. (Si la lista se quedara vaca hacer que Lc tome el valor NULL). Por ltimo se libera la memoria ocupada por el nodo.

Listas circulares.
Ejemplo 2. Eliminacin en lista circular ant->sig = ptrnodo->sig; if (Lc == Lc->sig) Lc=NULL; else if (ptrnodo == Lc) Lc = ant->sig;

Listas circulares.
Ejemplo 3 /***lista circular doblemente enlazada, que guarde enteros, y luego permita determinar cuantas veces se encuentra un nmero ingresado por el usuario.***/ #include <stdio.h> #include<stdlib.h> #include <conio.h> #include <string.h> /*Version Circular doblememente enlazada*/ typedef struct tipoNodo { int x; struct tipoNodo *adelante; struct tipoNodo *atras; }Nodo;

Listas circulares.
/*Declaracion de los sinonimos para referirnos al tipo de dato*/ typedef Nodo *tLista; typedef Nodo *tPosicion; int cont=0; /*Declaracin de las funciones que utilizaremos*/ void insertarPrim (tLista cabeza, int entrada); tLista CrearNodo(); void ImprimeLista(Nodo *ptr); int buscar(int busca, Nodo *cabeza, Nodo *ptr);

Listas circulares.
main() { /*inicio del programa principal*/ Nodo *ptr; tPosicion cabeza; int entrada, opc, busca; char ban; /*cabeza contiene la direccin del primer nodo creado*/ cabeza=CrearNodo(); ban='S'; printf("\n\t PROGRAMA QUE CALCULA LOS VALORES REPETIDOS EN UNA LISTA "); printf("\n\t DOBLEMENTE ENLAZADA ");

Listas circulares.
while(ban=='S' || ban=='s') { printf("\n\n Ingrese un elemento para la lista:\n"); scanf("%d", &entrada); cont++;
/*le enviamos a la funcin de insertar, le enviamos la direccin del primer nodo y el valor que vamos a introducir*/ insertarPrim(cabeza, entrada); printf("Desea Introducir un nuevo elemento a la lista? (S/N)\n"); ban=getch(); }

Listas circulares.
printf("Los Valores Guardados en la Lista son:\n");
/*la funcin de imprimir, recibe un puntero hacia el primer nodo para iniciar con la impresin*/ ImprimeLista(cabeza); getch(); printf("\n\t\tQue desea Hacer?\n"); printf("\t\t1.Buscar un valor en la lista\n"); printf("\t\t2.Salir\n"); scanf("%d", &op);

Listas circulares.
switch(opc) { case 1: printf("Ingrese el valor que desea buscar en la lista:\n"); scanf("%d", &busca); printf("El valor %d se encuentra %d veces en la lista\n\n", busca,buscar(busca,cabeza, cabeza)); break; case 2:exit(1); default:printf("Error, el comando no es vlido\n"); break; } getch(); return 0; }

Listas circulares.
/*definicin de las funciones*/ void insertarPrim(tPosicion cabeza, int entrada) { tPosicion nuevo; /*creamos un nuevo nodo y le asignamos la direccin de memoria*/ nuevo=(tPosicion)malloc(sizeof(Nodo)); if(nuevo==NULL) printf("ERROR\n"); nuevo->x=entrada; /*la parte de adelante del nuevo nodo, apunta al primer nodo*/ nuevo->adelante=cabeza; nuevo->atras=cabeza->atras; cabeza->atras->adelante=nuevo; cabeza->atras=nuevo; }

Listas circulares.
tLista CrearNodo() { /*creamos un nuevo nodo, el cual ser la "cabeza" de la lista*/ tLista L; L=(tLista)malloc(sizeof(Nodo)); if(L==NULL); printf("Error, memoria Insuciente\n"); L->adelante=L->atras=L; return L; }

Listas circulares.
void ImprimeLista(Nodo *ptr) { Nodo *p; int k=0; if(ptr!=NULL) { printf("Lista de Nmeros Guardados:\n"); p=ptr->adelante; do{ k++; if(k<=cont) printf("\t\t\t* %d *\n", p->x); p=p->adelante; }while(p!=ptr->adelante); } Else { printf("No Hay elementos en la Lista\n"); }

Listas circulares.
int buscar(int busca, Nodo *cabeza, Nodo *ptr) { int k=0; if(ptr!=NULL) { cabeza=ptr->adelante; do{ if(cabeza->x==busca) k++; cabeza=cabeza->adelante; }while(cabeza!=ptr->adelante); } else { printf("No Hay elementos en la Lista\n"); } return k; }