Foros del Web » Programación para mayores de 30 ;) » C/C++ »

implementación árboles binarios y colas

Estas en el tema de implementación árboles binarios y colas en el foro de C/C++ en Foros del Web. Buen día, quisiera pedir orientación sobre éste programa, es un programa que captura datos y los forma en un árbol binario, ya comprobé y el ...
  #1 (permalink)  
Antiguo 21/11/2012, 16:38
Avatar de paula23andrea  
Fecha de Ingreso: noviembre-2012
Mensajes: 38
Antigüedad: 12 años
Puntos: 1
Exclamación implementación árboles binarios y colas

Buen día, quisiera pedir orientación sobre éste programa, es un programa que captura datos y los forma en un árbol binario, ya comprobé y el árbol está bien creado, el problema está en el recorrido, que es por amplitud y necesita el uso de colas, en la función eliminar señalé un system pause en la instrucción donde está ''reventando'' que ni siquiera es un ciclo...

Código C++:
Ver original
  1. #include <iostream>
  2. using namespace std;
  3.  
  4. struct nodo
  5. {
  6.  int info, p;
  7.  nodo *llink;
  8.  nodo *rlink;
  9. };
  10.  
  11. #define maxcola 30
  12. struct COLA
  13. {
  14.  int fr;
  15.  int fin;
  16.  struct nodo *cont[maxcola];
  17. };
  18.  
  19. bool colallena (struct COLA *cola)
  20. {
  21.      bool valor;
  22.      int pos;
  23.      if (cola->fin==maxcola) pos = 0;
  24.      else pos = cola->fin;
  25.      
  26.      if ((cola->fr==pos)&& (cola->fin!=0)) valor=true;
  27.      else valor = false;
  28.      
  29.      return valor;
  30. }      
  31.  
  32. void insertarcola(struct COLA *cola, struct nodo *p)
  33. {
  34.   if (colallena (cola) == false){
  35.   if (cola->fin==maxcola)  cola->fin=1;        
  36.   else cola->fin=cola->fin + 1;
  37.          
  38.   cola->cont[cola->fin]=p;          
  39.   }
  40.   else cout << "\nERROR: No se puede insertar en la cola, ya que esta llena";
  41. }
  42.  
  43. bool colavacia (struct COLA *cola)
  44. {
  45.      bool valor;
  46.      if ((cola->fr==0)&& (cola->fin==0))valor=true;
  47.      else valor = false;
  48.      return valor;
  49. }
  50.  
  51. void limpiarcola(struct COLA *cola) {
  52.     cola->fr=0;
  53.     cola->fin=0;
  54. }
  55.  
  56. void eliminarcola(struct COLA *cola, struct nodo **q){
  57.    
  58.    
  59.     if (colavacia(cola)==false){
  60.         system("pause");  // al ejecutarse llega acá y revienta.
  61.         if (cola->fr == maxcola) cola -> fr = 1; // no sé qué tiene mal esa instrucción
  62.         else cola->fr=cola->fr + 1;
  63.        
  64.         *q=cola->cont[cola->fr];
  65.        
  66.         if (cola->fr == cola->fin) limpiarcola (cola);
  67.                
  68.         }
  69.     else cout << "\nERROR: No se puede eliminar de la cola, ya que esta vacia";    
  70.    
  71.    
  72.    
  73.     }
  74.  
  75. int pedir_info();
  76. nodo *crear_nodo(int);
  77. void insertar_nodo(nodo **, int);
  78. void recorrer(nodo *);
  79.  
  80. int pedir_info()
  81. {
  82.  int dato;
  83.  cout<<endl<<"Ingrese el valor para el arbol: "<<endl;
  84.  cin>>dato;
  85.  return dato;
  86. }
  87.  
  88. nodo *crear_nodo(int dato)
  89. {
  90.       nodo *aux;
  91.       aux=(nodo *)malloc(sizeof(nodo));
  92.       aux->info=dato;
  93.       aux->llink=NULL;
  94.       aux->rlink=NULL;
  95.  
  96.       return aux;
  97. }  
  98.  
  99. void insertar_nodo(nodo **arbol, int dato)
  100. {
  101.      if(*arbol != NULL)
  102.      {
  103.         if(dato < (*arbol)->info)
  104.            insertar_nodo(&((*arbol)->llink), dato);
  105.         else
  106.            insertar_nodo(&((*arbol)->rlink), dato);
  107.     }
  108.      else
  109.          *arbol=crear_nodo(dato);
  110. }
  111.  
  112.  
  113. void recorrer(nodo *arbol)
  114. {
  115.  COLA actual;  
  116.  nodo *p;    
  117.  insertarcola(&actual, arbol);
  118.  
  119.  while(colavacia(&actual)==false)
  120.  {
  121.  eliminarcola(&actual, &p); // acá hace el llamado a la función
  122.  cout<<p->info;
  123.  
  124.  if(p->llink!=NULL)
  125.  insertarcola(&actual, p->llink);
  126.  
  127.  if(p->rlink!=NULL)
  128.  insertarcola(&actual, p->rlink);
  129. }
  130. }
  131.  
  132.    
  133.  
  134. int main()
  135. {
  136.  nodo *arbol=NULL;
  137.  int dato=0;
  138.  char fin='n';
  139.  
  140.  while(fin=='n')
  141.  {
  142.   dato=pedir_info();
  143.   insertar_nodo(&arbol, dato);
  144.   cout<<endl<<"Termino de ingresar? (y/n)"<<endl;              
  145.   cin>>fin;
  146.   }
  147.  
  148.  recorrer(arbol);
  149.  
  150. system("pause");


Muchas gracias a quien se tome el tiempo de copiarlo a un compilador y me pueda explicar!
  #2 (permalink)  
Antiguo 22/11/2012, 04:58
 
Fecha de Ingreso: agosto-2012
Mensajes: 601
Antigüedad: 12 años, 3 meses
Puntos: 83
Respuesta: implementación árboles binarios y colas

El problema lo tienes en que no inicializas los datos de la estructura COLA: cuando declaras una variable y no inicializas, cualquier operacion que no sea de asignacion se hace contra datos basura del bloque de memoria al que está apuntando la variable; te pongo un ejemplo de lo que sucede:

Código:
COLA actual;
actual.fin += 1;
printf("%d", actual.fin);
Que crees que se mostrará por pantalla? 1?? Se puede dar la remota casualidad que el dato basura guardado en actual.fin equivalga al entero 0 y el resultado de la suma sea 1, pero es posible que aun provando infinitas veces no se cumpliera.

En la funcion 'recorrer()' declaras 'COLA actual' y seguidamente la envias sin inicializar a la funcion 'insertarcola()' donde lo primero que hace es comprobar si la cola está llena, te dejo una ayuda para ver como funciona por dentro esta primera llamada, que provoca un error que se arrastra por las demas funciones (será tu tarea ver el flujo de datos por dentro de las demas funciones, y tambien sobre cualquier funcion que hagas a partir de ahora ya sea sobre este programa o sobre cualquier otro):

Código:
bool colallena (struct COLA *cola) {
        bool valor;
        int pos;
        
        if (cola->fin==maxcola) {
            pos = 0;
        }
        else {
            pos = cola->fin;
        }
        
        if((cola->fr==pos)&& (cola->fin!=0)) {
            valor=true;
        }
        else {
            valor = false;
        }
        
        return valor;
    }
El primer condicional raramente se cumplirá porque 'cola->fin' llegó sin inicializar y aun contiene datos basura, luego por defecto siempre se cumple el 'else', con lo que asignas a 'pos' el dato basura de 'cola->fin'. Vas al siguiente condicional y comparas otra variable no inicializada que contiene datos basura con la variable 'pos' que segun el condicional anterior le has asignado otro dato basura, el resultado es que nunca (sería mucha casualidad) se cumplirá el segundo condicional, con lo que resuelve diciendo siempre que COLA está vacía, ok?

Solucion: inicializar todas las variables antes de hacer operaciones sobre ellas. Por suerte para ti la implementacion es muy simple, antes de usar COLA actual tienes que asignar un dato base a las variables

Código:
COLA actual;

actual.fin = 0;
actual.fr = 0;
Ya tienes tu programa funcionando.

Ahora echa un vistazo a tu funcion 'nodo *crear_nodo(int dato)', que pasa con las variables 'llink' y 'rlink'? Que sucedería si no las inicializas con NULL y las dejas apuntando al bloque de memoria que se le asigna el procesador?

Mas cosas, cuando bloqueas memoria dinamica debes hacer la comprovacion de error para el caso de que no haya disponible:

Código:
nodo *aux = (nodo *)malloc(sizeof(nodo));
if(!aux) {/*error*/}
Pero esto se hace en C, en c++ se recomienda no usar malloc para bloquear memoria dinamica, con 'new' puedes hacer lo mismo (y obviamente hacer las comprovaciones de error que con 'new' tienes que hacer con exceptions). Ademas en c++ usa los 'static_cast<tipo>' en vez de los typecast de C. En tu caso creo que no hay problema con eso, de todas formas te lo comento:

Código:
aux = new (nothrow) nodo;
if(!aux) {/*error*/}
Y cuando usas memoria dinamica tienes que liberarla cuando ya no la necesites; todos los bloques de memoria reservados con 'malloc' (en c++ con 'new') tienes que liberarlos con 'free' (en c++ con 'delete') (en c++ con new y delete hay varias cosas a tener en cuenta, mejor echa un vistazo a algun manual).

Saludos
vosk
  #3 (permalink)  
Antiguo 22/11/2012, 05:44
 
Fecha de Ingreso: noviembre-2012
Mensajes: 24
Antigüedad: 12 años
Puntos: 3
Respuesta: implementación árboles binarios y colas

En tu otro tema, te comente el algoritmo que podes utilizar en pseudocodigo, el mismo recorrera en amplitud el arbol.

Saludos.
  #4 (permalink)  
Antiguo 22/11/2012, 20:27
Avatar de paula23andrea  
Fecha de Ingreso: noviembre-2012
Mensajes: 38
Antigüedad: 12 años
Puntos: 1
Respuesta: implementación árboles binarios y colas

Aprendí muchísimo con la respuesta de vosk, y sí el problema esencial era no haber inicializado la cola, lo demás lo tendré en cuenta, porque el uso de malloc es formato obligatorio de mi profesor de estructuras...

Enserio muchas gracias por tomarte el tiempo, ya me ha quedado todo claro :D
Ahora debo enfrentarme a herencias con clases y objetos, pero es otro tema que si me causa mucha dificultad recurriré a ustedes :)

Etiquetas: colas, estructuras, funciones, arboles
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 11:41.