mergemap.cpp
// $Id$
/*
COMIENZO DE DESCRIPCION
__USE_WIKI__
Dadas dos correspondencias #A# y #B#, que asocian
enteros con listas ordenada de enteros, escribir una
funcion
#void merge_map(map<int,list<int>> &A, map<int,list<int>> &B, map<int,list<int>> &C)# que
devuelve en #C# una correspondencia que asigna al
elemento #x# la fusion ordenada de las dos listas #A[x]#
y #B[x]#. Si #x# no es clave de #A#, entonces #C[x]#
debe ser #B[x]# y viceversa. Por ejemplo:
si #M={(1,2),(2,5),(3,4),(4,6),(5,2)}# entonces #cyclic(M,L)#
debe dejar #L=(1,2,5)#.
[Tomado en 1er parcial 25-SEP-2008].
keywords: correspondencia, lista
FIN DE DESCRIPCION */
// -----------------------------------------------------------------
#include <cstdio>
#include <cassert>
#include <list>
#include <vector>
#include <map>
#include <algorithm>
using namespace std ;
typedef list<int> list_t;
typedef list_t::iterator liter;
typedef map<int,list<int> > map_t;
typedef map_t::iterator miter;
//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
// Pone en C la fusion ordenada de 2 listas ordenadas
// A y B. Elementos repetidos aparecen tantas veces como
// en cada uno de los originales (i.e. preserva el numero
// de elementos). OJO L1, L2 y L deben ser
// objetos diferentes.
void merge(list_t &L1,list_t &L2,list_t &L) {
liter
q1 = L1.begin(),
q2 = L2.begin();
// Avanza el menor y pone su valor al final de L
while ((q1 != L1.end()) && (q2 != L2.end())) {
if (*q1 <= *q2) L.insert(L.end(),*q1++);
else L.insert(L.end(),*q2++);
}
// Inserta las colas de L1 y L2, notar
// que no importa el orden ya que a esta altura
// alguna de las dos esta vacia
while (q1 != L1.end()) L.insert(L.end(),*q1++);
while (q2 != L2.end()) L.insert(L.end(),*q2++);
}
//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
// Agrega las asignaciones de A a las de C. Es decir si A
// asigna a x la lista La y C le asigna Lc, entonces despues
// de hacer add_map(A,C) en C[x] queda merge(La,Lc)
void add_map(map_t &A, map_t&C) {
// Recorre las asignaciones de A
miter qa = A.begin();
while (qa!=A.end()) {
// clave de la asignacion
int ka = qa->first;
// Busca si la clave esta asignada en C
miter qc = C.find(ka);
// Si la clave no esta asignada en C
// crea una asignacion con la lista nula
if (qc == C.end()) C[ka] = list_t();
// A esta altura C *seguro* tiene una
// asignacion para ka
qc = C.find(ka);
assert(qc != C.end());
// hace la fusion de las listas en la lista
// temporaria L. OJO, no se puede hacer in-place
// es decir merge(qa->second,qc->second,qc->second);
// ya que los argumentos de merge deben ser diferentes.
list_t L;
merge(qa->second,qc->second,L);
// Copia el resultado de merge en la asignacion de C
qc->second = L;
qa++;
}
}
//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
void merge_map(map_t &A, map_t &B, map_t&C) {
C.clear();
// Simplemente agrega las asignaciones de A y B en C
add_map(A,C);
add_map(B,C);
}
//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
// Genera un mapa aleatorio de `nk' claves en [0,NK)
// a listas de lingitud aleatoria (en promedio NL)
// de elementos en [0,M)
void rand_map(int nk,int NK, int nl, int NL, map_t &M) {
// genera nk enteros diferentes en [0,NK)
// para eso introduce los enteros de [0,NK)
// en un vector, hace el random_shuffle() y
// toma los nk primeros
vector<int> v(NK);
for (int j=0; j<NK; j++) v[j] = j;
random_shuffle(v.begin(),v.end());
// para cada clave asigna una lista aleatoria
for (int j=0; j<nk; j++) {
M[v[j]] = list_t();
list_t &L = M[v[j]];
int len = rand() % (2*nl);
for (int j=0; j<len; j++)
L.insert(L.end(),rand()%NL);
// Ordena la lista
L.sort();
}
}
//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
// Imprime la correspondencia
void print_map(map_t &M) {
miter p = M.begin();
while (p != M.end()) {
printf("%d: ",p->first);
list_t &L = p->second;
liter q = L.begin();
while (q != L.end())
printf(" %d",*q++);
printf("\n");
p++;
}
}
//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
int main() {
// genera dos corresnpondencias aleatorias
// A, B. Las concatena en C e imprime
map_t A,B,C;
rand_map(5,10,5,10,A);
printf("A: --------\n");
print_map(A);
rand_map(5,10,5,10,B);
printf("B: --------\n");
print_map(B);
merge_map(A,B,C);
printf("C: --------\n");
print_map(C);
}
Generated by GNU Enscript 1.6.6.