cyclic.cpp
// $Id$
/*
COMIENZO DE DESCRIPCION
__USE_WIKI__
Dada una correspondecia #M# y un elemento #x0#, podemos
generar una secuencia #(x0,x1,x2,...)# de la forma
#x_{k+1}=M(x{k})#. La secuencia se detiene cuando uno de
los valores #x_k# generados no pertenece a las claves de
#M#. En ese caso la secuencia generada es finita. Por
otra parte, puede ocurrir que un elemento de la
secuencia se repita, es decir #x_{k+m}=x_k# con
#m>0#. Es obvio que, a partir de alli la secuencia se va
a repetir indefinidamente. _Consigna:_ escribir una
Escribir una funcion
#void cyclic(map<int,int> &M,list<int> &L);#
que extrae en #L# todas aquellas
claves de #M# que generan una secuencia ciclica
infinita. Por ejemplo, si
#M={(1,2),(2,5),(3,4),(4,6),(5,2)}# entonces
#cyclic(M,L)# debe retornar #L=(1,2,5)#.
[Tomado en 1er parcial 25-SEP-2008].
keywords: correspondencia, lista
FIN DE DESCRIPCION */
// -----------------------------------------------------------------
#include <cstdio>
#include <list>
#include <map>
using namespace std ;
//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
// Predicado que determina si el elemento x
// esta en la lista L
int contains(list<int> &L,int x) {
list<int>::iterator p = L.begin();
while (p != L.end())
if (x == *p++) return 1;
return 0;
}
//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
// Verifica si la secuencia generada por x_{k+1} = M(x_k)
// es finita o no
int is_cyclic(map<int,int> &M, int x) {
list<int> L;
L.insert(L.end(),x);
while (1) {
// verifica si x tiene un valor asignado
// o no. OJO: no se deben generar asociaciones
// espurias.
map<int,int>::iterator p = M.find(x);
// Si no tiene asignacion entonces es un terminador
if (p==M.end()) return 0;
// Genera el siquiente elemento de la secuencia
x=p->second;
// Verifica si ya esta en la lista o no.
// Si ya esta entonces es ciclica
if (contains(L,x)) return 1;
L.insert(L.end(),x);
}
}
//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
// Extrae las claves ciclicas de M recorriendo
// las claves y aplicando el predicado `is_cyclic'.
void cyclic(map<int,int> &M, list<int> &L) {
map<int,int>::iterator q = M.begin();
while (q != M.end()) {
if (is_cyclic(M,q->first))
L.insert(L.end(),q->first);
q++;
}
}
//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
int main() {
const int ntest = 20;
// Repite el test ntest veces
for (int j=0; j<ntest; j++) {
list<int> L;
// Genera un mapa aleatorio
// Las claves y valores en [0,N).
map<int,int> M;
const int N=20;
for (int j=0; j<N; j++) {
int k = rand() % N;
int v = rand() % N;
M[k] = v;
}
map<int,int>::iterator r = M.begin();
while (r!=M.end()) {
printf("M[%d] = %d\n",r->first,r->second);
r++;
}
cyclic(M,L);
list<int>::iterator q = L.begin();
printf("cyclic keys: ");
while (q!=L.end())
printf(" %d",*q++);
printf("\n");
printf("cyclic %d, not cyclic %d\n",L.size(),N-L.size());
printf("---------\n");
}
}
Generated by GNU Enscript 1.6.6.