//Arboles Binarios
Ejercicio 1
//Se define una relación de orden entre árboles binarios de enteros de la siguiente //forma: A<B si a<b, o bien (a=b y Ai < Bi), o bien (a=b y Ai=Bi y Ad<Bd), donde
//a, b son las raíces y Ai, Ad, Bi, Bd son los subárboles izquierdos y derechos de A y B. //Consigna: Escribir una función bool es_menor(tree<int> &A,tree<int> &B)
//que retorna verdadero si A < B. [Tomado en el 2do parcial 26/5/2005].
bool es_menor(btree<int> &T1,btree<int>::iterator n1, btree<int> &T2,btree<int>::iterator n2) { // Si los dos estan vacios, entonces no cae en
// ninguno de los casos especificados y debe // retornar false.
if (n1==T1.end() && n2==T2.end()) return false; // Si `n1==end()' y `n2!=end()' entonces
// `*n1<*n2' y debe retornar `true'. if (n1==T1.end()) return true;
// Si `n1!=end()' y `n2==end()' entonces
// `*n1>*n2' y no entra en ninguno de los casos,
// por lo tanto debe retornar `false'. if (n2==T2.end()) return false;
// Las dos raices son dereferenciables.
// Si son distintas ya puede retornar un valor.
if (*n1 < *n2) return true; if (*n1 > *n2) return false;
// Si llega aqui, las dos raices son dereferenciables // e iguales. Hay que comparar los arboles de los hijos.
// Si `Ai' y `Bi' son diferentes retornar un valor...
if (es_menor(T1,n1.left(),T2,n2.left())) return true;
if (es_menor(T2,n2.left(),T1,n1.left())) return false;
// ... finalmente retorna el valor de comparacion // de los hijos derechos.
return es_menor(T1,n1.right(),T2,n2.right()); }
// `wrapper'
bool es_menor(btree<int> &T1,btree<int> &T2) { return es_menor(T1,T1.begin(),T2, T2.begin()); }
Ejercicio 2
// Cuando se define una relacion de orden vimos que basta
// con definir <, >, <= o >=. Una alternativa es una
// funcion `comp(a,b)' que retorna -1 si T1<T2, 0 si T1==T2,
// Esta funcion seria el operador `comp' para // arboles binarios. Ademas, esta implementacion
// permite pasar una funcion de comparacion
// (programacion funcional)
int comp_btree(btree<int> &T1,btree<int>::iterator n1, btree<int> &T2,btree<int>::iterator n2,
int (*comp)(int x,int y)) { // Si son Lambda => son iguales.
if (n1==T1.end() && n2==T2.end()) return 0; // Si `n1==end()' y `n2!=end()'
// entonces `*n1<*n2'.
// debe retornar -1.
if (n1==T1.end()) return -1;
// Si `n1!=end()' y `n2==end()' // entonces `*n1>*n2'.
if (n2==T2.end()) return +1;
// Si `comp(*n1,*n2)!=0' entonces debe
// retornar el valor de `comp'
int v = comp(*n1,*n2); if (v) return v;
// Si `comp_btree(Ai,Bi) != 0' entonces debe
// retornar el valor.
v = comp_btree(T1,n1.left(),T2,n2.left(),comp); if (v) return v;
// Retorna el valor `comp_btree(Ai,Bi) != 0'
return comp_btree(T1,n1.right(),T2,n2.right(),comp); }
// `wrapper'
int comp_btree(btree<int> &T1, btree<int> &T2,
int (*comp)(int x,int y)) {
comp_btree(T1,T1.begin(),T2,T2.begin(),comp); }
// Funcion de comparacion para enteros.
int comp(int x,int y) { return (y<x) - (x<y); }
// Funcion de comparacion para enteros,
// correspondiente a la relacion de orden (debil) // |a|<|b|
int comp_abs(int x,int y) {
int yy = abs(y);
int xx = abs(x);
return (yy<xx) - (xx<yy);
}
int M=5;
bool equalp(btree<int> &A, btree<int>::iterator a, btree<int> &B, btree<int>::iterator b,
bool (*eq)(int x,int y)) {
if ((a == A.end()) != (b == B.end())) return false; if (a == A.end()) return true;
if (!eq(*a,*b)) return false;
return equalp(A,a.left(),B,b.left(),eq) && equalp(A,a.right(),B,b.right(),eq); }
bool equalp(btree<int> &A, btree<int> &B,
bool (*eq)(int x,int y)) {
return equalp(A,A.begin(),B,B.begin(),eq); }
bool odd(int x) { return x %2; }
bool equal(int x,int y) { return x==y; }
Ejercicio 3
//Escribir una función predicado bool contenido(btree<int> &A, btree<int> &B);
//que retorna verdadero si la estructura del árbol binario A esta ``contenido'' //dentro de la de B y las etiquetas correspondientes de A son menores que las de B+.
//[Tomado en el examen 2do parcial del 27/5/2004].
bool contenido(btree<int> &A,btree<int>::iterator na, btree<int> &B,btree<int>::iterator nb) { if (na==A.end()) return true;
if (nb==B.end()) return false; if (*na>*nb) return false;
if (!contenido(A,na.left(),B,nb.left())) return false; if (!contenido(A,na.right(),B,nb.right())) return false;
return true; }
bool contenido(btree<int> &A,btree<int> &B) { return contenido(A,A.begin(),B,B.begin()); }
Ejercicio 4
//Igual a cumsum.cpp pero ahora para AB. El cumsum(v) de un vector v es la suma acumulada, //es decir en la posicion v[j] debe quedar la suma de los elementos de v[0..j].
//Para un arbol lo podemos extender diciendo que en cada nodo del arbol queda la suma //de los valores de los nodos de su subarbol ANTES de la operacion.
//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
void cumsum_down(btree<int> &T,node_t p, int sum) { // sum es la suma acumulada hasta el padre de p
if (p==T.end()) return; // actualiza el valor de p
// propaga a los hijos cumsum_down(T,p.left(),*p); cumsum_down(T,p.right(),*p); }
//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*> // Wrapper
void cumsum_down(btree<int> &T) { cumsum_down(T,T.begin(),0); }
//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
void cumsum_up(btree<int> &T,node_t p) { if (p==T.end()) return;
node_t l = p.left(), r = p.right(); // aplica a los hijos
cumsum_up(T,l); cumsum_up(T,r);
// actualiza el valor de p
if (l!=T.end()) *p += *l; if (r!=T.end()) *p += *r;
}
//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*> // Wrapper
void cumsum_up(btree<int> &T) { cumsum_up(T,T.begin());
}
Ejercicio 5
//Dados un arbol binario T encontrar la maxima profundidad de un nodo tal que
//satisface un predicado dado. [Tomado en el 2do parcial del 2009-10-27].
int depth_if(btree<int> &T,btree<int>::iterator n, pred_t pred) { if (n==T.end()) return -1;
int dl,dr,dn,depth;
dl = depth_if(T,n.left(),pred); dr = depth_if(T,n.right(),pred); depth = (dl>dr? dl : dr);
return (depth>=0? depth+1 : pred(*n)? 0 : -1); }
//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
// Wrapper
int depth_if(btree<int> &T,pred_t pred) { return depth_if(T,T.begin(),pred); }
//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
bool odd(int x) { return x%2; }
Ejercicio 6
//Listado de arboles binarios en diferentes ordenes.
//
---void orden_post ( btree <int> & t, btree <int> :: iterator n) { if ( n == t.end () ) return ;
orden_post (t, n.left () ) ; orden_post (t, n.right () ) ; cout << (* n) << " " ;
} // end void
//
---void orden_sime ( btree <int> & t, btree <int> :: iterator n) { if ( n == t.end () ) return ;
orden_sime (t, n.left () ) ; cout << (* n) << " " ;
orden_sime (t, n.right () ) ; } // end void
Ejercicio 7
//Dados dos enteros M y n, tales que n<M crear un arbol binario completo (ABC) //T tal que: 1) La suma de las hojas es M, pero cada una de ellas es h<=n. 2)
//Se satisface que para cada nodo n la suma de sus dos hijos l y r es n=lr+. //Ayuda: El arbol se puede construir poniendo inicialmente M en la raiz,
//y dividiendo cada nodo por 2 hasta obtener valores <=n
//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
void split_down(btree<int> &T, btree<int>::iterator p,int n) { // Se supone que `p' es dereferenciable. Fijarse
// que despues le aplica el `split_down()' solo a nodos // dereferenciables.
// Si el contenido del nodo es menor que `n' ya esta.
if (*p <= n) return;
// Divide el contenido de `p' en `r' y `l'
// de tal manera que son approx *p/2 // (pero la suma se preserva)
int r = *p/2, l = *p-r;
// Inserta los nuevos nodos y les aplica // recursivamente el `split_down()'
T.insert(p.left(),r); split_down(T,p.left(),n);
T.insert(p.right(),l); split_down(T,p.right(),n); }
//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
void split_down(int M,btree<int> &T,int n) { T.clear();
// Inicialmente inserta `M' en la raiz.
// Notar que esto garantiza que despues
// la `split_down()' recursiva se aplica solo
// a nodos dereferenciables. T.insert(T.begin(),M);
split_down(T,T.begin(),n); }
Ejercicio 8
//Funciones Varias
//
---int altura (btree<int> & T, btree<int>:: iterator n) {
int h1, h2, hmax ;
// la recursion finaliza cuando ingresa los hijos de las hojas if (n == T.end ()) return -1 ;
// altura del sub-arbol izquierdo "h1" y derecho "h2" por recursion h1 = altura (T, n.left () ) ;
h2 = altura (T, n.right () ) ;
// selecciona la mayor altura de los subarboles izquierdo y derecho
if (h1 > h2) { hmax = h1 ; } else {
hmax = h2 ; } // end if
// devuelve la mayor altura return (1 + hmax) ;
} // end int
//
---int cta_hojas (btree<int> & T, btree<int>:: iterator n) {
int p1, p2, p ;
bool b1, b2 ;
// la recursion finaliza cuando ingresa los hijos de las hojas if ( n == T.end () ) return 0 ;
// si el nodo "n" es hoja entonces devuelve 1 b1 = ( n.left () == T.end () ) ;
b2 = ( n.right () == T.end () ) ; if ( b1 && b2 ) return 1 ;
// cta hojas sub-arbol izquierdo "p1" y derecho "p2" por recursion p1 = cta_hojas ( T, n.left () );
p2 = cta_hojas ( T, n.right () );
// devuelve la suma de las hojas de los sub-arboles izq. y der.
p = p1 + p2 ; return p ; } // end int
//
---int max_etiq_arbol (btree<int> & T, btree<int>:: iterator n) {
// la recursion finaliza cuando ingresa los hijos de las hojas if (n == T.end ()) return -1;
// max etiq. de los subarb. izq. "x1" y der. "x2" por recursion
x1 = max_etiq_arbol (T, n.left () ) ; x2 = max_etiq_arbol (T, n.right () ) ;
// selecciona y devuelve "xmax" como el mayor de (*n, x1, x2) xmax = *n ;
if (x1 > xmax) xmax = x1 ; if (x2 > xmax) xmax = x2 ; return xmax ;
} // end int
//
---int max_etiq_hojas (btree<int> & T, btree<int>:: iterator n) {
int x, x1, x2, xmax ;
bool b1, b2 ;
// la recursion finaliza cuando ingresa los hijos de las hojas
if (n == T.end ()) return -1 ;
// si el nodo "n" es hoja entonces devuelve su etiqueta
x = *n ;
b1 = ( n.left () == T.end () ) ; b2 = ( n.right () == T.end () ) ; if (b1 && b2) return x ;
// max etiq_hojas de los subarb. izq. "x1" y der. "x2" por recursion x1 = max_etiq_hojas (T, n.left ());
x2 = max_etiq_hojas (T, n.right ());
// selecciona y devuelve "xmax" como el mayor de (*n, x1, x2)
xmax = 0 ;
if (x1 > xmax) xmax = x1 ; if (x2 > xmax) xmax = x2 ; return xmax;
} // end int
//
---int max_epar_arbol (btree<int> & T, btree<int>:: iterator n) {
int x1, x2, xmax ;
// la recursion finaliza cuando ingresa los hijos de las hojas if (n == T.end ()) return -1;
// max etiq. par de los subarb. izq. "x1" y der. "x2" por recursion x1 = max_epar_arbol (T, n.left () ) ;
x2 = max_epar_arbol (T, n.right () ) ;
// selecciona y devuelve "xmax" como el mayor par de (*n, x1, x2)
if (*n % 2 == 0) xmax = *n ; else xmax = 0 ; if (x1 > xmax && x1 % 2 == 0) xmax = x1 ; if (x2 > xmax && x2 % 2 == 0) xmax = x2 ; return xmax ;
} // end int
//
---int sum_etiq_arbol (btree<int> &T, btree<int>::iterator n) {
int s1, s2, suma ;
// la recursion finaliza cuando ingresa los hijos de las hojas
// suma recursiva de las etiq. de los subarb. izq. "s1" y der. "s2" s1 = sum_etiq_arbol (T, n.left ());
s2 = sum_etiq_arbol (T, n.right ());
// devuelve "suma" como la suma de (*n, s1, s2) suma = *n + s1 + s2;