HerenciaOrdenada.cpp

Ir a la documentación de este archivo.
00001 // HerenciaOrdenada.cpp (c) 2005 [email protected]
00002 
00003 /** \file  HerenciaOrdenada.cpp
00004     \brief Ejemplo de uso de funciones virtuales usando algoritmos de ordenamiento.
00005 
00006     \author Alejandro Di Mare <[email protected]>
00007     \author Adolfo Di Mare <[email protected]>
00008     \date   2005
00009 */
00010 
00011 #define  INCLUDE_iostream
00012 #include "conio.h"
00013 #include "ADH_port.h"  // Biblioteca de compatibilidad BC++ v3.1 && MS C++
00014 
00015 #include <cstdlib>
00016 #include <ctime>
00017 #include "rational.h"
00018 USING_namespace(ADH);
00019 
00020 /// Clase abstracta cuyos hijos son contenedores que pueden ser ordenados.
00021 /// - Tanto la \c "Lista_Ordenable" como el \c "Vector_Ordenable" son sus clases derivadas
00022 class Contenedor_Ordenable {
00023 protected:
00024     /// Cantidad de valores almacenados en el \c "Contenedor_Ordenable"
00025     int m_cantidad_de_elementos;
00026 
00027 public:
00028     typedef rational value_type; ///< Tipo de valor almacenado en el contenedor
00029 
00030     Contenedor_Ordenable(unsigned N); ///< Constructor
00031     virtual ~Contenedor_Ordenable(); ///< Destructor
00032 
00033     /// Intercambia los valores de los elementos que están
00034     /// en las posiciones [i] <=> [j].
00035     virtual void Intercambie(int i, int j) = 0;
00036 
00037     /// Compara los elementos en las dos posiciones \c "i" && \c "j" del contenedor.
00038     /// - Retorna \c "true" cuando el primero es menor que el segundo.
00039     /// - Retorna \c "false" cuando el primero es mayor o igual que el segundo.
00040     ///   \pre <code>(i < Dimension()) && (j < Dimension())</code>
00041     virtual bool Es_Menor(int, int) const = 0;
00042 
00043         /// Muestra el i-ésimo término del contenedor \c V[i]
00044     virtual value_type& operator[](int) = 0;
00045 
00046     /// Devuelve la cantidad de valores almacenados en el \c "Contenedor_Ordenable".
00047     unsigned Dimension() const { return m_cantidad_de_elementos; }
00048 
00049     /// Graba en \c "cout" todos los valores almacenados en el contendor.
00050     /// - Los graba en el orden en el que se encuentran almacenados.
00051     virtual void ImprimaSe() const = 0;
00052 
00053     /// Nombre del contenedor
00054     virtual const char* Nombre() const = 0;
00055 };
00056 
00057 
00058 /// Lista ordenable simple, compuesta de nodos, que almacena números enteros.
00059 /// - Este \c "Contenedor_Ordenable" es una lista de enteros de tamaño
00060 ///   \c "Contenedor_Ordenable::_cantidad_de_elementos".
00061 class Lista_Ordenable : public Contenedor_Ordenable {
00062 
00063 private:
00064     /// Nodos de la \c "Lista_Ordenable"
00065     class Nodo {
00066     public:
00067         /// Construye un nuevo \c "Nodo" cuyo valor almacenado es \c "v"
00068         Nodo(value_type v);
00069         ~Nodo(); ///< Destructor
00070 
00071         Nodo *     next;  ///< Puntero al próximo nodo
00072         value_type m_val; ///< Valor entero almacenado en el nodo
00073         };
00074 
00075     /// Agrega una copia de \c "v" al prinicipio de \c "*this"
00076     void Agregar_Valor(value_type v);
00077 
00078 public:
00079     /// Constructor que inserta \c "N" valores (aleatorios) en el contenedor.
00080     Lista_Ordenable(unsigned N);
00081     virtual ~Lista_Ordenable(); ///< Destructor
00082 
00083     virtual void Intercambie(int, int);
00084     virtual bool Es_Menor(int, int) const;
00085         virtual value_type& operator[](int);
00086 
00087     virtual void ImprimaSe() const;
00088     virtual const char* Nombre() const;
00089         /*virtual int Obtener_Valor(int);
00090         virtual void Inserta_Valor(int, int);*/
00091 private:
00092     Nodo * m_cabeza; ///< Primer \c "Nodo" de la lista
00093 };
00094 
00095 
00096 /// Vector ordenable que almacena enteros.
00097 /// - Este \c "Contenedor_Ordenable" es un vector de enteros de tamaño
00098 ///   \c "Contenedor_Ordenable::m_cantidad_de_elementos"
00099 class Vector_Ordenable : public Contenedor_Ordenable {
00100 
00101 private:
00102     value_type * m_vec;
00103 
00104 
00105 public:
00106     /// Constructor que inserta \c "N" valores (aleatorios) en el contenedor.
00107     Vector_Ordenable(unsigned N);
00108     virtual ~Vector_Ordenable(); ///< Destructor
00109 
00110     virtual void Intercambie(int, int);
00111     virtual bool Es_Menor(int, int) const;
00112         virtual value_type& operator[](int);
00113 
00114     virtual void ImprimaSe() const;
00115     virtual const char* Nombre() const;
00116 };
00117 
00118 
00119 /// Clase abstracta que se usa para derivar de ella los algoritmos
00120 /// que sirven para ordenar instancias de \c "Contenedor_Ordenable".
00121 /// - No contiene campo alguno; sirve como "funtor" polimórfico.
00122 class Algoritmo_Ordenador {
00123 private: // "Rep vacío"
00124 public:
00125     /// Este es el método que hace todo el trabajo.
00126     /// - Ordena el \c "Contenedor_Ordenable" usando el
00127     ///   \c "Algoritmo_Ordenador"
00128     virtual void Ordene(Contenedor_Ordenable &C) = 0;
00129 
00130     Algoritmo_Ordenador(); ///< Constructor
00131     virtual ~Algoritmo_Ordenador(); ///< Destructor
00132 
00133     // Nombre del algoritmo de ordenamiento
00134     virtual const char* Nombre() const = 0;
00135 };
00136 
00137 
00138 /// Clase de empaque alrededor del método de ordenamiento por "Burbuja".
00139 /// - Está derivada de \c "Algoritmo_Ordenador" para homologar su funcionalidad.
00140 /// - El método \c Ordene() es el que implementa el algoritmo de ordenamiento.
00141 class Ordenador_Burbuja : public Algoritmo_Ordenador {
00142 public:
00143     Ordenador_Burbuja(); ///< Constructor
00144     virtual ~Ordenador_Burbuja(); ///< Destructor
00145 
00146     /// Método que realiza el ordenamiento por "Burbuja".
00147     virtual void Ordene(Contenedor_Ordenable &);
00148     /// Retorna en nombre \c "Ordenador_Burbuja".
00149     virtual const char* Nombre() const;
00150 };
00151 
00152 
00153 /// Clase de empaque alrededor del método de ordenamiento por "Burbuja Optimizada".
00154 /// - Está derivada de \c "Algoritmo_Ordenador" para homologar su funcionalidad.
00155 /// - El método \c Ordene() es el que implementa el algoritmo de ordenamiento.
00156 class Ordenador_Burbuja_Optimizada : public Algoritmo_Ordenador {
00157 public:
00158     Ordenador_Burbuja_Optimizada(); ///< Constructor
00159     virtual ~Ordenador_Burbuja_Optimizada(); ///< Destructor
00160 
00161     /// Método que realiza el ordenamiento por "Burbuja Optimizada".
00162     virtual void Ordene(Contenedor_Ordenable &);
00163     /// Retorna en nombre \c "Ordenador_Burbuja_Optimizada".
00164     virtual const char* Nombre() const;
00165 };
00166 
00167 
00168 /// Clase de empaque alrededor del método de ordenamiento por "Selección".
00169 /// - Está derivada de \c "Algoritmo_Ordenador" para homologar su funcionalidad.
00170 /// - El método \c Ordene() es el que implementa el algoritmo de ordenamiento.
00171 class Ordenador_Seleccion : public Algoritmo_Ordenador {
00172 public:
00173     Ordenador_Seleccion(); ///< Constructor
00174     virtual ~Ordenador_Seleccion(); ///< Destructor
00175 
00176     virtual void Ordene(Contenedor_Ordenable &);
00177     /// Retorna en nombre \c "Ordenador_Seleccion".
00178     virtual const char* Nombre() const;
00179 };
00180 
00181 
00182 /// Clase de empaque alrededor del método de ordenamiento por "Insertion Sort".
00183 /// - Está derivada de \c "Algoritmo_Ordenador" para homologar su funcionalidad.
00184 /// - El método \c Ordene() es el que implementa el algoritmo de ordenamiento.
00185 class Ordenador_Insertion_Sort : public Algoritmo_Ordenador {
00186 public:
00187         Ordenador_Insertion_Sort();///<Constructor
00188         virtual ~Ordenador_Insertion_Sort(); ///<Destructor
00189 
00190         virtual void Ordene(Contenedor_Ordenable &);
00191     /// Retorna en nombre \c "Insertion_Sort"".
00192     virtual const char* Nombre() const;
00193 };
00194 
00195 
00196 /// Clase de empaque alrededor del método de ordenamiento por "Merge Sort".
00197 /// - Está derivada de \c "Algoritmo_Ordenador" para homologar su funcionalidad.
00198 /// - El método \c Ordene() es el que implementa el algoritmo de ordenamiento.
00199 class Ordenador_Merge_Sort : public Algoritmo_Ordenador {
00200 public:
00201         Ordenador_Merge_Sort();///<Constructor
00202         virtual ~Ordenador_Merge_Sort(); ///<Destructor
00203 
00204         virtual void Ordene(Contenedor_Ordenable &);
00205         void m_sort(Contenedor_Ordenable &, rational [], int, int);
00206         void merge(Contenedor_Ordenable &, rational [], int, int, int);
00207 
00208     /// Retorna en nombre \c "Merge_Sort"".
00209     virtual const char* Nombre() const;
00210 };
00211 
00212 
00213 Lista_Ordenable::Lista_Ordenable(unsigned N) : Contenedor_Ordenable(N) {
00214     m_cabeza = 0;
00215     this->m_cantidad_de_elementos = N;
00216 
00217     srand(time(0));
00218     for (unsigned i = 0; i < N; ++i) {
00219         Agregar_Valor( rand() % 100 );
00220     }
00221 }
00222 
00223 Lista_Ordenable::~Lista_Ordenable() {
00224     if (m_cabeza != 0) {
00225         delete m_cabeza;
00226     }
00227 }
00228 
00229 Lista_Ordenable::Nodo::Nodo(value_type v) {
00230     this->m_val = v;
00231     next = 0;
00232 }
00233 
00234 Lista_Ordenable::Nodo::~Nodo() {
00235     // Implementación recursiva de la destrucción de la lista de nodos
00236     if (next != 0) {
00237         delete next; // HORRIBLE: ==> Usa O( size() ) espacio
00238     }
00239 }
00240 
00241 void Lista_Ordenable::Agregar_Valor(value_type v) {
00242     if (m_cabeza == 0) {
00243         m_cabeza = new Nodo(v);
00244     }
00245     else {
00246         Nodo * p  = new Nodo(v);
00247         p->next   = m_cabeza;
00248         m_cabeza    = p;
00249     }
00250 }
00251 
00252 void Lista_Ordenable::Intercambie(int i, int j) {
00253     Nodo * pI = m_cabeza;
00254     Nodo * pJ = m_cabeza;
00255 
00256     int k;
00257     for (k = 0; k < i; ++k) {
00258         pI = pI->next;
00259     }
00260     for (k = 0; k < j; ++k) {
00261         pJ = pJ->next;
00262     }
00263 
00264     value_type temp;
00265     temp = pJ->m_val;
00266     pJ->m_val = pI->m_val; // NO intercambia los nodos
00267     pI->m_val = temp;      // intercambia los valores
00268 }
00269 
00270 bool Lista_Ordenable::Es_Menor(int i, int j) const {
00271     Nodo * pI = m_cabeza;
00272     Nodo * pJ = m_cabeza;
00273 
00274     int k;
00275     for (k = 0; k < i; ++k) {
00276         pI = pI->next;
00277     }
00278 
00279     for (k = 0; k < j; ++k) {
00280         pJ = pJ->next;
00281     }
00282     return (pI->m_val  <  pJ->m_val);
00283 }
00284 
00285 rational& Lista_Ordenable::operator[](int i) {
00286     Nodo * pI = m_cabeza;
00287 
00288     int k;
00289     for (k = 0; k < i; ++k) {
00290         pI = pI->next;
00291     }
00292     return pI->m_val;
00293 }
00294 
00295 void Lista_Ordenable::ImprimaSe() const {
00296     Nodo * p = m_cabeza;
00297     Nodo * end = 0;
00298     cout << "[";
00299     while (p != end) {
00300         cout << p ->m_val;
00301         if (p->next != end) { // ¿último nodo de la lista?
00302             cout << " ";
00303         }
00304         p = p->next;
00305     }
00306     cout << "]" << endl;
00307 }
00308 
00309 const char* Lista_Ordenable::Nombre() const {
00310     #ifdef    __BORLANDC__
00311         // Este método no puede ser definido dentro de la clase porque
00312         // BC++ lo considera "inline", lo que impide que sea "virtual"
00313     #endif // __BORLANDC__
00314     return "Lista_Ordenable";
00315 }
00316 Vector_Ordenable::Vector_Ordenable(unsigned N) : Contenedor_Ordenable(N) {
00317     // assert( N == m_cantidad_de_elementos );
00318     m_vec = new Contenedor_Ordenable::value_type [ m_cantidad_de_elementos ];
00319     srand( time(0) );
00320 
00321     for (int i = 0; i < m_cantidad_de_elementos; ++i) {
00322         m_vec[i] = rand() % 100;
00323     }
00324 }
00325 
00326 Vector_Ordenable::~Vector_Ordenable() {
00327     if (m_vec != 0) {
00328         delete [] m_vec;
00329     }
00330 }
00331 
00332 void Vector_Ordenable::ImprimaSe() const {
00333     value_type * p = m_vec;
00334     value_type * end = & m_vec[ m_cantidad_de_elementos ];
00335     cout << "[";
00336     while (p != end) {
00337         cout << *p;
00338         if (p+1 != end) { // ¿último valor del vector?
00339            cout << " ";
00340         }
00341         p++;
00342     }
00343     cout << "]" << endl;
00344 }
00345 
00346 bool Vector_Ordenable::Es_Menor(int i, int j) const {
00347     return (m_vec[i] < m_vec[j]);
00348 }
00349 
00350 rational& Vector_Ordenable::operator[](int i) {
00351     return m_vec[i];
00352 }
00353 
00354 void Vector_Ordenable::Intercambie(int i, int j) {
00355     value_type temp;
00356 
00357     temp   = m_vec[i];
00358     m_vec[i] = m_vec[j];
00359     m_vec[j] = temp;
00360 }
00361 
00362 const char* Vector_Ordenable::Nombre() const {
00363     return "Vector_Ordenable";
00364 }
00365 
00366 void Ordenador_Burbuja::Ordene(Contenedor_Ordenable & C) {
00367     int i,j;
00368     for (i = C.Dimension(); i > 0; --i) {
00369         for (j = 1; j < i; j++) {
00370             if ( C.Es_Menor(j, j-1) ) {
00371                 C.Intercambie(j, j-1);
00372             }
00373         }
00374     }
00375 }
00376 
00377 void Ordenador_Burbuja_Optimizada::Ordene(Contenedor_Ordenable & C) {
00378     bool cambio = true;
00379     for (int i = C.Dimension(); i > 0 && cambio; --i) {
00380         cambio = false;
00381         for (int j = 1; j < i; j++) {
00382             if ( C.Es_Menor(j, j-1) ) {
00383                 C.Intercambie(j, j-1);
00384                 cambio = true;
00385             }
00386         }
00387     }
00388 }
00389 
00390 void Ordenador_Seleccion::Ordene(Contenedor_Ordenable & C) {
00391     int n = C.Dimension();
00392     for (int i=0; i < n-1; i++) {
00393         int menor = i;
00394 
00395         for (int j=i+1; j<n; j++) {
00396             if (C.Es_Menor(j,menor)) {
00397                 menor = j;
00398             }
00399         }
00400         C.Intercambie(i, menor);
00401     }
00402 }
00403 
00404 
00405 void Ordenador_Insertion_Sort::Ordene(Contenedor_Ordenable & C){
00406         int n= C.Dimension();
00407         for (int i=1; i < n; i++){
00408                 int j= i-1;
00409                 while (C.Es_Menor(i,j)){
00410                         C.Intercambie(i,j);
00411                         i--;
00412                         j--;
00413                 }
00414         }
00415 }
00416 
00417 void Ordenador_Merge_Sort::Ordene(Contenedor_Ordenable & C){
00418         int tamañoTotal= C.Dimension();
00419         int primero=0;
00420         rational vec_Temporal [20];
00421         m_sort (C,vec_Temporal,primero,tamañoTotal-1);
00422 
00423 }
00424 
00425 void Ordenador_Merge_Sort::m_sort(Contenedor_Ordenable & C, rational vector [],int inicio,int fin){
00426         int mitad;
00427 
00428         if (fin > inicio){
00429                 mitad= (fin + inicio)/2;
00430                 m_sort( C, vector, inicio, mitad);
00431                 m_sort( C, vector, mitad+1, fin);
00432 
00433                 merge(C, vector, inicio, mitad+1, fin);
00434         }
00435 }
00436 
00437 void Ordenador_Merge_Sort:: merge(Contenedor_Ordenable & C,rational vector[],int inicio, int mitad, int tamaño){
00438         int i, final_izquierda, num_elements, tmp_pos;
00439         
00440 
00441         final_izquierda = mitad - 1; ///Marca el ultimo indice de la primera mitad del contenedor
00442         tmp_pos = inicio;
00443         num_elements = (tamaño - inicio);
00444 
00445         while ((inicio <= final_izquierda) && (mitad <= tamaño)){
00446                 if (C[inicio]<=C[mitad]){
00447                         vector[tmp_pos]= C[inicio];
00448                         tmp_pos++;
00449                         inicio++;
00450                 }
00451                 else{
00452                         vector[tmp_pos]= C[mitad];
00453                         tmp_pos++;
00454                         mitad++;
00455                 }
00456         }
00457 
00458         while (inicio <= final_izquierda){
00459                 vector[tmp_pos]= C[inicio];
00460                 inicio++;
00461                 tmp_pos++;
00462         }
00463         while (mitad <= tamaño){
00464                 vector[tmp_pos]= C[mitad];
00465                 mitad++;
00466                 tmp_pos++;
00467         }
00468         
00469         for (i=0; i <= num_elements; i++){
00470                 C[tamaño]= vector[tamaño];
00471                 tamaño--;
00472                 }
00473 }
00474 
00475 Contenedor_Ordenable::Contenedor_Ordenable(unsigned N)
00476     : m_cantidad_de_elementos(N) {
00477 }
00478 
00479 Contenedor_Ordenable::~Contenedor_Ordenable() {
00480     // No hace nada porque no usa memoria dinámica
00481 }
00482 
00483 Algoritmo_Ordenador::Algoritmo_Ordenador() {
00484     // No hace nada porque el "Rep" está vacío
00485 }
00486 
00487 Algoritmo_Ordenador::~Algoritmo_Ordenador() {
00488     // No hace nada porque el "Rep" está vacío
00489 }
00490 
00491 Ordenador_Burbuja::Ordenador_Burbuja() {
00492     // No hace nada porque el "Rep" está vacío
00493 }
00494 
00495 Ordenador_Burbuja::~Ordenador_Burbuja() {
00496     // No hace nada porque el "Rep" está vacío
00497 }
00498 
00499 const char* Ordenador_Burbuja::Nombre() const {
00500     return "Ordenador_Burbuja";
00501 }
00502 
00503 Ordenador_Seleccion::Ordenador_Seleccion() {
00504     // No hace nada porque el "Rep" está vacío
00505 }
00506 
00507 Ordenador_Seleccion::~Ordenador_Seleccion() {
00508     // No hace nada porque el "Rep" está vacío
00509 }
00510 
00511 const char* Ordenador_Seleccion::Nombre() const {
00512     return "Ordenador_Seleccion";
00513 }
00514 
00515 Ordenador_Burbuja_Optimizada::Ordenador_Burbuja_Optimizada() {
00516     // No hace nada porque el "Rep" está vacío
00517 }
00518 
00519 Ordenador_Burbuja_Optimizada::~Ordenador_Burbuja_Optimizada() {
00520     // No hace nada porque el "Rep" está vacío
00521 }
00522 
00523 const char* Ordenador_Burbuja_Optimizada::Nombre() const {
00524     return "Ordenador_Burbuja_Optimizada";
00525 }
00526 
00527 Ordenador_Insertion_Sort::Ordenador_Insertion_Sort() {
00528     // No hace nada porque el "Rep" está vacío
00529 }
00530 
00531 Ordenador_Insertion_Sort::~Ordenador_Insertion_Sort() {
00532     // No hace nada porque el "Rep" está vacío
00533 }
00534 
00535 const char* Ordenador_Insertion_Sort::Nombre() const {
00536     return "Ordenador_Insertion_Sort";
00537 }
00538 
00539 Ordenador_Merge_Sort::Ordenador_Merge_Sort() {
00540     // No hace nada porque el "Rep" está vacío
00541 }
00542 
00543 Ordenador_Merge_Sort::~Ordenador_Merge_Sort() {
00544     // No hace nada porque el "Rep" está vacío
00545 }
00546 
00547 const char* Ordenador_Merge_Sort::Nombre() const {
00548     return "Ordenador_Merge_Sort";
00549 }
00550 
00551 
00552 /// Retorna \c "true" cuando el contenedor \c "C" está ordenado no decrecientemente.
00553 bool Esta_Ordenado ( const Contenedor_Ordenable &C ) {
00554     unsigned i;
00555     for (i = 0; i < C.Dimension()-1; ++i) {
00556         if ( C.Es_Menor(i+1,i) ) {
00557             return false;
00558         }
00559     }
00560     return true;
00561 }
00562 
00563 #include <assert.h>
00564 
00565 /// Rutina principal del programa.
00566 /// - En cada iteración de su ciclo principal elije un contenedor para almacenar
00567 ///   valores (lista vs vector), y un algoritmo de ordenamiento
00568 ///   (Burbuja vs Burbuja_Optimizada vs Seleccion).
00569 int main() {
00570     Algoritmo_Ordenador  * pOrdenador;  // puntero "polimórfico" para el algoritmo
00571     Contenedor_Ordenable * pContenedor; // puntero "polimórfico" para el contenedor
00572     srand( time(0) );
00573     cout << endl << endl << endl;
00574     for (int i = 0; i < 5; ++i) {         // Algoritmo_Ordenador
00575         for (int j = 0; j < 2; ++j) {     // Contenedor_Ordenable
00576 
00577             cout << endl;
00578             cout << "======================";
00579             cout << "======================";
00580             cout << "======================" << endl;
00581 
00582             // Selecciona el algoritmo de ordenamiento
00583             switch ( i ) {
00584                 case 0: pOrdenador = new Ordenador_Burbuja();            break;
00585                 case 1: pOrdenador = new Ordenador_Burbuja_Optimizada(); break;
00586                 case 2: pOrdenador = new Ordenador_Seleccion();          break;
00587                                 case 3: pOrdenador = new Ordenador_Insertion_Sort();     break;
00588                                 case 4: pOrdenador = new Ordenador_Merge_Sort();                 break;
00589             }
00590 
00591             // Selecciona "Lista_Ordenable" o "Vector_Ordenable" como contenedor
00592             switch ( j ) {
00593                 case 0: pContenedor = new Vector_Ordenable( 20 ); break;
00594                 case 1: pContenedor = new Lista_Ordenable(  20 ); break;
00595             }
00596 
00597             cout << "<<< " << 2*i+j+1 << " >>> => ";
00598             cout << pContenedor->Nombre() << " <===> ";
00599             cout << pOrdenador->Nombre() << endl;
00600             // Se imprime la lista desordenada generada al azar
00601             cout << endl << "[Sin orden]: ";
00602             pContenedor->ImprimaSe();
00603 
00604             pOrdenador->Ordene( *pContenedor );
00605             cout << endl << "[Ordenados]: ";
00606             pContenedor->ImprimaSe();
00607 
00608             if (! Esta_Ordenado( *pContenedor ) ) {
00609                 cout << endl;
00610                 cout << "ERRROR: El contenedor " << pContenedor->Nombre() << " NO está ordenado" << endl;
00611                 assert( "ERRROR: El contenedor NO está ordenado" && false );
00612             }
00613 
00614             // Destruye "pOrdenador" && "pContenedor"
00615             delete pOrdenador;
00616             delete pContenedor;
00617         }
00618     }
00619         getch();
00620     return 0;
00621 }
00622 // EOF: HerenciaOrdenada.cpp

Generado el Mon Sep 11 00:19:12 2006 para Herencia Ordenada: por  doxygen 1.4.7
Hosted by www.Geocities.ws

1