lesser.cpp
// $Id$
/* COMIENZO DE DESCRIPCION
__USE_WIKI__
Se define una relaci\'on de orden entre AOO de enteros de
la siguiente forma: #A<B# si
#(na,c0a,c1a,c2a...)<(nb,c0b,c1b,c2b...)#, donde #na# es
la raiz de #A#, #h0a# el subarbol del primer hijo de #A#
y asi siguiendo. En la expresion anterior se toma el orden
lexicografico para listas y se asume que en caso de tener
longitudes diferentes se completa con -infinito.
keywords: arbol orientado
FIN DE DESCRIPCION */
// -------------------------------------------------------------------
#include <cstdarg>
#include <cstdio>
#include <iostream>
#include <map>
#include <set>
#include <algorithm>
#include "./util.h"
#include "./tree.h"
#include "./util_tree.h"
using namespace aed;
using namespace std;
//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
// Comparacion por < de arboles
bool lesser_aux(tree<int> &A,tree<int>::iterator na,
tree<int> &B,tree<int>::iterator nb) {
// Primero vemos si algunas de las raices es Lambda.
// Si A=Lambda y B!=Lambda entonces A<B
// Si A=B=Lambda A==B
// Si A!=Lambda y B=Lambda A>B
if (nb==B.end()) return false;
if (na==A.end()) return true;
// Ninguno es Lambda, comparamos los valores
if (*na!=*nb) return *na<*nb;
// Ahora vamos comparando uno a unos los hijos.
// No tenemos comparacion por diferencia, asi que hacemos
// !a<b y !b<a
node_t
ca = na.lchild(),
cb = nb.lchild();
while (ca!=A.end() && cb!=B.end()) {
if (lesser_aux(A,ca,B,cb)) return true;
if (lesser_aux(B,cb,A,ca)) return false;
ca++; cb++;
}
// Si llegamos aca alguna de las listas de hijos es end.
// Solo es A<B si el que es end() es ca y cb no.
return ca==A.end() && cb!=B.end();
}
//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
// Makes a random tree with `s' siblings and `m' nodes
void make_random_tree2(tree<int> &T,tree<int>::iterator n,
int M, int m,int s) {
if (!m) return;
// Toma los m nodos y los divide en `ss' siblings donde s es aleatorio
// en [1,s]
int ss = rand()%s+1;
// Inserta un nodo en la raiz
n = T.insert(n,rand()%M);
m--; // toma en cuenta que ya inserto 1
// Reparte los nodos que quedan aleatoriamente en los ss hijos
vector<int> v(ss,0);
for (int j=0; j<m; j++) v[rand()%ss]++;
// A esta altura tenemos un vectos v[] con s enteros
// cuya suma es `m'. Algunos pueden ser nulos, pero no importa
// porque en ese caso la llamada recursiva no va a hacer nada.
for (int j=0; j<v.size(); j++)
make_random_tree2(T,n.lchild(),M,v[j],s);
}
//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
// Wrapper
void make_random_tree2(tree<int> &T,int M, int m,int s) {
make_random_tree2(T,T.begin(),M,m,s);
}
//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
// Wrapper para la funcion de comparacion.
// (No se porque el compilador patalea si tiene el mismo nombre
// que la auxiliar, por eso le pongo comp2).
bool lesser(tree<int> A,tree<int> B) {
return lesser_aux(A,A.begin(),B,B.begin());
}
//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
// Predicado de igualdad para arboles
bool equal(tree<int> &T1,tree<int>::iterator n1,
tree<int> &T2,tree<int>::iterator n2) {
// Si uno es Lambda y el otro no: false
if ((n1==T1.end()) != (n2==T2.end())) return false;
// Si n1==end entonces n2 tambien y por lo tanto: true
if (n1==T1.end()) return true;
// Si los valores son distintos: false
if (*n1 != *n2) return false;
// Compara recursivamente los hijos
tree<int>::iterator c1 = n1.lchild(), c2 = n2.lchild();
while (c1!=T1.end() && c2!= T2.end()) {
// Si no son iguales los subarboles: false
if (!equal(T1,c1,T2,c2)) return false;
c1++; c2++;
}
// Si en alguno de los dos quedo algo: falso, si no: true
return (c1!=T1.end()) == (c2!=T2.end());
}
//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
// Wrapper
bool equal(tree<int> &T1,tree<int> &T2) {
return equal(T1,T1.begin(),T2,T2.begin());
}
//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
int main() {
typedef tree<int> tree_t;
// TEST 2
int N=50;
vector<tree_t> treev(N);
// Genera N arboles aleatorios y los ordena
// (ahi usa la funcion de comparacion)
printf("----------------\nNO ORDENADOS:\n");
for (int j=0; j<N; j++) {
// make_random_tree(treev[j],10,1.0);
make_random_tree2(treev[j],3,5,2.0);
printf("treev[%d]: ",j);
treev[j].lisp_print();
printf("\n");
}
sort(treev.begin(),treev.end(),lesser);
printf("----------------\nORDENADOS:\n");
for (int j=0; j<N; j++) {
printf("treev[%d]: ",j);
treev[j].lisp_print();
printf("\n");
}
// TEST 2, genera M pares de arboles y los compara
// Uno solo de los siguientes puede ser verda:
// T1<T2, T1==T2 o T1>T2. Chequea esto para los M pares.
int bad=0,ok=0,M=10000;
for (int j=0; j<M; j++) {
tree_t T1,T2;
make_random_tree2(T1,3,5,2.0);
make_random_tree2(T2,3,5,2.0);
int l=lesser(T1,T2),
e=equal(T1,T2),
g=lesser(T2,T1),
f = (l+g+e==1);
ok += f;
bad += !f;
// printf("T1<T2 %d, T1==T2 %d, T1>T2 %d, ok? %d\n",
// l,g,e,f);
if (!ok) {
// No se cumplio la condicion, error
printf("T1: ");
T1.lisp_print();
printf("\n");
printf("T2: ");
T2.lisp_print();
printf("\n--------------\n");
int b = lesser(T1,T2);
printf("lesser(T1,T2) %d\n",b);
b = lesser(T2,T1);
printf("lesser(T2,T1) %d\n",b);
exit(0);
}
}
printf("Tested %d, ok %d, bad %d\n",M,ok,bad);
return 0;
}
Generated by GNU Enscript 1.6.6.