Documente Academic
Documente Profesional
Documente Cultură
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 #include <stdio.h> #include <stdlib.h> #include <time.h> /* estructura autoreferenciada */struct nodoArbol { struct nodoArbol *ptrIzq; /* apuntador al subrbol izquierdo */ int dato; /* valor del nodo */ struct nodoArbol *prtDer; /* apuntador al subrbol derecho */ }; /* fin de la estructura nodoArbol */ typedef struct nodoArbol NodoArbol; /* sinnimo de la estructura nodoArbol */ typedef NodoArbol *ptrNodoArbol; /* sinnimo de NodoArbol* */ /* prototipos */void insertaNodo( ptrNodoArbol *ptrArbol, int valor ); void inOrden( ptrNodoArbol ptrArbol ); void preOrden( ptrNodoArbol ptrArbol ); void postOrden( ptrNodoArbol ptrArbol ); /* la funcin main comienza la ejecucin del programa */ int main() { int i; /* contador para el ciclo de 1 a 10 */ int elemento; /* variable para almacenar valores al azar */ ptrNodoArbol ptrRaiz = NULL; /* rbol inicialemnte vaco */ srand( time( NULL ) ); printf( "Los numeros colocados en el arbol son:n" ); /* inserta valores al azar entre 1 y 15 en el rbol */ for ( i = 1; i <= 10; i++ ) { elemento = rand() % 15; printf( "%3d", elemento ); insertaNodo( &ptrRaiz, elemento ); } /* fin de for */ /* recorre el rbol en preorden */ printf( "nnEl recorrido en preorden es:n" ); preOrden( ptrRaiz ); /* recorre el rbol en in inorden */ printf( "nnEl recorrido inorden es:n" ); inOrden( ptrRaiz ); /* recorre el rbol en postOrden */ printf( "nnEl recorrido en postOrden es:n" ); postOrden( ptrRaiz ); return 0; /* indica terminacin exitosa */ } /* fin de main */ /* inserta un nodo dentro del rbol */ void insertaNodo( ptrNodoArbol *ptrArbol, int valor ){ /* si el rbol esta vaco */ if ( *ptrArbol == NULL ) {
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
*ptrArbol = malloc( sizeof( NodoArbol ) ); /* si la memoria est asignada, entonces asigna el dato */ if ( *ptrArbol != NULL ) { ( *ptrArbol )->dato = valor; ( *ptrArbol )->ptrIzq = NULL; ( *ptrArbol )->prtDer = NULL; } /* fin de if */ else { printf( "no se inserto %d. No hay memoria disponible.n", valor ); } /* fin de else */ } /* fin de if */ else { /* el rbol no esta vaco */ */ /* el dato a insertar es menor que el dato en el nodo actual if ( valor < ( *ptrArbol )->dato ) { insertaNodo( &( ( *ptrArbol )->ptrIzq ), valor ); } /* fin de if */ /* el dato a insertar es mayor que el dato en el nodo actual else if ( valor > ( *ptrArbol )->dato ) { insertaNodo( &( ( *ptrArbol )->prtDer ), valor ); } /* fin de else if */ else { /* ignora el valor duplicado del dato */ printf( "dup" ); } /* fin de else */ } /* fin de else */ } /* fin de la funcin insertaNodo */ /* comienza el recorrido inorden del rbol */ void inOrden( ptrNodoArbol ptrArbol ) { /* si el rbol no esta vaco, entonces recrrelo */ if ( ptrArbol != NULL ) { inOrden( ptrArbol->ptrIzq ); printf( "%3d", ptrArbol->dato ); inOrden( ptrArbol->prtDer ); } /* fin de if */ } /* fin de la funcin inOrden */ /* comienza el recorrido preorden del rbol */void preOrden( ptrNodoArbol ptrArbol ) { /* si el rbol no esta vaco, entonces recrrelo */ if ( ptrArbol != NULL ) { printf( "%3d", ptrArbol->dato ); preOrden( ptrArbol->ptrIzq ); preOrden( ptrArbol->prtDer ); } /* fin de if */ } /* fin de la funcin preOrden */ /* comienza el recorrido postOrden del rbol */ void postOrden( ptrNodoArbol ptrArbol ) { /* si el rbol no esta vaco, entonces recrrelo */ if ( ptrArbol != NULL ) { postOrden( ptrArbol->ptrIzq );
*/
110 postOrden( ptrArbol->prtDer ); 111 >dato ); 112 } /* fin de if */ 113 114 } /* fin de la funcin postOrden */ 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
ejecutado
en
Borland
C++
5.0
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
srand( time( NULL ) ); printf( "Los numeros colocados en el arbol son:n" ); /* inserta valores al azar entre for ( i = 1; i dato = valor; NULL; ( *ptrArbol )->prtDer = } /* fin de if */ else { printf( "no se inserto %d. valor ); } } else { /* el arbol no esta vacio 1 y 15 en el arbol */ ( *ptrArbol )->ptrIzq = NULL; No hay memoria disponible.n", */
/* el dato a insertar es menor que el dato en el nodo actual */ if ( valor dato ) { insertaNodo( &( ( *ptrArbol )->ptrIzq ), valor ); } /* el dato a insertar es mayor que el dato en el nodo actual */ else if ( valor > ( *ptrArbol )->dato ) { insertaNodo( &( ( *ptrArbol )->prtDer ), valor ); } else { /* ignora el valor duplicado del dato */ printf( "# " ); // Imprime en valores duplicados } } } /* fin de la funcion insertaNodo */ /* comienza el recorrido inorden del arbol */ void inOrden( ptrNodoArbol ptrArbol ){ /* si el arbol no esta vacio, entonces recorrelo */ if ( ptrArbol != NULL ) { inOrden( ptrArbol->ptrIzq ); printf( "%3d", ptrArbol->dato ); inOrden( ptrArbol->prtDer ); } } /* fin de la funcion inOrden */ /* comienza el recorrido preorden del arbol */ void preOrden( ptrNodoArbol ptrArbol ){ /* si el arbol no esta vacio, entonces recorrelo */ if ( ptrArbol != NULL ) { printf( "%3d", ptrArbol->dato ); preOrden( ptrArbol->ptrIzq ); preOrden( ptrArbol->prtDer ); } } /* fin de la funcion preOrden */ /* comienza el recorrido postOrden del arbol */ void postOrden( ptrNodoArbol ptrArbol ){ /* si el arbol no esta vacio, entonces recorrelo */ if ( ptrArbol != NULL ) { postOrden( ptrArbol->ptrIzq ); postOrden( ptrArbol->prtDer ); printf( "%3d", ptrArbol->dato ); } } /* fin de la funcion postOrden */
78 79 80 81 82
printf("\n\n\tIntroduzca una cadena de caracteres (max. 200 elementos):\n "); gets(chain); elementos=strlen(chain); //CHECA EL TAMAO DE LA CADENA Y ESTABLE CE EL NUMERO DE NODOS DEL ARBOL for(i=1;i<=elementos;i++) { newnod=chain[i-1]; insertanodonuevo(&raiz,newnod); } printf("\n\n preorden \t"); preorden(raiz); //LLAMADO A FUNCION DE DEN printf("\n\n inorden \t"); inorden(raiz); //LLAMADO A FUNCION DE EN printf("\n\n postorden \t"); postorden(raiz); //LLAMADO A FUNCION DE RDEN getch(); treefree(raiz); //LIBERACION DE MEMORIA DEL raiz=NULL; //ASIGNACION DE UN VALOR NULO return 0; }
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*/ /*CREA UN NUEVO NODO Y COLOCA LOS VALORES DEL NUEVO ELEMENTO EN LA POSICION CORRESPONDIENTE */ void insertanodonuevo(ARBOL *rarbol,int nuevo){ if(*rarbol==NULL){ //CREACION DE UN NUEVO NODO *rarbol=(NODO *)malloc(sizeof(NODO)); if(*rarbol!=NULL){ //ASIGNACION DE VALORES NUEVOS EN EL NODO NUEVO (*rarbol)->info=nuevo; (*rarbol)->izqnodo =NULL; (*rarbol)->dernodo=NULL; } else{printf("\n Memoria No Disponible !!!!\n");} } else if(nuevo<(*rarbol)>info) //checa si el elemento nuevo es mayor que el elemento padre insertanodonuevo(&((*rarbol)>izqnodo),nuevo); //coloca el elemento a la izquierda del padre o raiz else if(nuevo>(*rarbol)>info) //checa si el elemento nuevo es menor que el elemento padre insertanodonuevo(&((*rarbol)>dernodo),nuevo); //coloca el elemento a la derecha del padre o raiz } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*/ //FUNCION ITERATIVA LA CUAL RECORRE EL ARBOL IMPRIMIENDO SIEMPRE EL VALOR
//QUE CONTIENE LA RAIZ,DESPUES LA RAMA IZQUIERDA,LUEGO LA RAMA DERECHA,SI EMPRE //Y CUANDO LA RAIZ SEA DIFERENTE DE UN VALOR NULO, SI ES NULO SALTA A LA SIGUIENTE INSTRUCCION. void preorden(ARBOL rarbol){ if(rarbol!=NULL){ printf(" %c ",rarbol->info); preorden(rarbol->izqnodo); preorden(rarbol->dernodo); } } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*/ //FUNCION ITERATIVA LA CUAL RECORRE EL ARBOL BUSCANDO EL NODO MAS IZQUIER DO //QUE CONTIENE EL ARBOL O SEA HASTA QUE LA RAMA DEL ULTIMO NODO SEA NULO, LUEGO LA IMPRIME,DESPUES //DESPUES LA RAIZ DEL SUB-ARBOL,Y LUEGO EL NODO DE LA DERECHA. void inorden(ARBOL rarbol){ if(rarbol!=NULL){ inorden(rarbol->izqnodo); printf(" %c ",rarbol->info); inorden(rarbol->dernodo); } } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*/ //FUNCION ITERATIVA LA CUAL RECORRE EL ARBOL BUSCANDO EL NODO QUE ESTA MA S A LA IZQUIERDA //LUEGO EL NODO DE LA DERECHA Y LUEGO LA RAIZ DE ESE SUB-ARBOL void postorden(ARBOL rarbol){ if(rarbol!=NULL){ postorden(rarbol->izqnodo); postorden(rarbol->dernodo); printf(" %c ",rarbol->info); } } /**-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*/ //FUNCION ITERATIVA IDENTICA AL RECORRIDO EN POSTORDEN LA UNICA DIFERENCI A //ES QUE EN VEZ DE IMPRIMIR EN PANTALLA EL VALOR DE UN NODO ESTE ES //ELIMINADO DEL ARBOL LIBERANDO LA MEMORIA CON LA FUNCION free(), ELEGI E STA //FORMA YA QUE SE ELIMINA PRIMERO LOS NODOS HIJO DE EL SUBARBOL Y LUEGO LA RAIZ //YA QUE SI SE ELIMINA LA RAIZ PRIMERO, LOS DATOS DE LOS HIJOS SE DESCONE CTAN //DEL ARBOL PERO LA MEMORIA QUE OCUPABAN SIGUE SIENDO UTILIZADA Y DE ESTA FORMA //SE ELIMINA EL ARBOL DE ABAJO HACIA ARRIBA (O SEA DE LOS HIJOS A LA RAIZ ).
void treefree(ARBOL rarbol){ if(rarbol!=NULL){ treefree(rarbol->izqnodo); treefree(rarbol->dernodo); free(rarbol); } } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*/ /********************************************* PROGRAMA ELABORADO EN COMPILADOR: TURBO C++ VERSION 3.0 BORLAND INTERNATIONAL --------------------------------------------- CODIGO FUENTE POR: DANIEL ALBERTO RIVERA PERALES. MATRICULA.- 185154 GRUPO: 4K **********************************************/ /********************************************* Cualquier duda o comentario sobre este programa por favor mandarlo a mi correo electronico. -> kropzter@yahoo.com -> a185154@uach.mx
} return NULL; } Por las razones expuestas al hablar de la recursin ( 4.4.6c), esta funcin no puede ser directamente utilizada en su forma actual, por lo que modificaremos ligeramente su diseo antes de su utilizacin en el siguiente ejemplo.
2 Ejemplo
Para comprobar la veracidad del cdigo, modificamos el programa del rbol binario mejorado de la pgina anterior, de forma que en cualquier momento, introduciendo el carcter "?", el programa realiza la bsqueda del siguiente carcter que se introduzca por teclado en vez de incluirlo en el rbol, que es el comportamiento normal. #include <iostream.h> struct base { char let; struct base* izq; struct base* der; } *rz, *aptr; // rbol binario con bsqueda // Estructura a utilizar
char previo, ant; // globales auxiliares int incluir(char letra, struct base* puntero); void inorden (struct base* puntero); char acepta (void); // aceptar datos del teclado void busca(char key, struct base* puntero); // buscar void nodo(struct base* puntero); // mostrar resultado de busqueda void main(void) { // ========================== char c; if ((rz = new(base)) == NULL) { // crear nodo raz cout << "NO queda memoria" << endl; return 1; } rz->let = '\\'; // carcter en el nodo raz rz->izq = rz->der = NULL; while ( (c = acepta()) != 27) { // Bucle principal if (c == '?') { previo = c; continue; } else if (previo == '?') { previo = c; aptr = NULL; busca(c, rz); // buscar caracter en el arbol nodo(aptr); // mostrar resultado de la busqueda continue; } else if (incluir(c, rz)) break; inorden(rz); }
} char acepta (void) { // Introducir datos por teclado char c; cout << "\n Pulse un caracter + [CR] "; while (1) { c = getchar(); if (c == 10) continue; // 10 == New Line if (c >= 65 && c <= 91) return c; if (c >= 97 && c <= 123 ) return c; if (c == 27 || c == '?') return c; cout << "\a"; } } int incluir(char letr, struct base* ptr) { // aadir elemento if (letr == ptr->let) return 0; // El carcter ya existe if (letr < ptr->let) { if (ptr->izq == NULL) { // enlace libre: incluir aptr = (struct base*) malloc(sizeof(base)); if (aptr == NULL) { cout << "Memoria agotada" << endl; return 1; } aptr->let = letr; aptr->izq = aptr->der = NULL; ptr->izq = aptr; return 0; } if (incluir(letr, ptr->izq)) return 1; // falla la insercin } if (letr > ptr->let) { if (ptr->der == NULL) { // enlace libre: incluir aptr = (struct base*) malloc(sizeof(base)); if (aptr == NULL) { cout << "Memoria agotada" << endl; return 1; } aptr->let = letr; aptr->izq = aptr->der = NULL; ptr->der = aptr; return 0; } if (incluir(letr, ptr->der)) return 1; // falla la insercin } return 0; } void inorden (struct base* ptr) { if (ptr == NULL) return; inorden(ptr->izq); cout << " - " << ptr->let; inorden(ptr->der); } // Recorrer rbol
// buscar key
if (key == ptr->let) { aptr = ptr; return; } ant = ptr->let; if (key < ptr->let) { // debe estar en rama izquierda if (ptr->izq == NULL) return; // no existe busca(key, ptr->izq); // seguir bsqueda } if (key > ptr->let) { // debe estar en rama derecha if (ptr->der == NULL) return; // no existe busca(key, ptr->der); // seguir bsqueda } return; } void nodo(struct base* ptr) { // mostrar resultado if (ptr == NULL) { cout << "No encontrado\a" << endl; return; } char izq = '#', der = '#', key = ptr->let; if (ptr->izq != NULL) izq = ptr->izq->let; // letra nodo izq. if (ptr->der != NULL) der = ptr->der->let; // letra nodo der. cout << "\n " << ant << endl; cout << " |" << endl; cout << " " << key << endl; cout << "/ \\" << endl; cout << izq << " " << der << endl; }
Comentario
Introducimos dos nuevas variables globales: previo y ant, que alojarn respectivamente el ltimo carcter pulsado, y el carcter del nodo anterior (raz) del que se busca. Igualmente introducimos dos nuevas funciones: busca y nodo. La primera ya se ha comentado, se utiliza para buscar un carcter. La segunda, a la que se pasa un puntero al nodo encontrado, muestra el detalle de los enlaces o anuncia el fallo en la bsqueda (el puntero es nulo). La funcin acepta ha sufrido un ligersimo cambio para permitir introducir el carcter "?"
3 Ejemplo
Como complemento del ejercicio anterior, presentamos una variante utilizando el manejador de excepciones C++ ( 1.6) para realizar un retorno desde la funcin busca hasta main cuando ocurre un encuentro. Se lanza entonces una excepcin que es precisamente el puntero al nodo encontrado. Esta excepcin es capturada y entonces se muestra el detalle del nodo. Como la funcin nodo solo es llamada en caso de bsqueda con xito, es necesario modificarla ligeramente y sacar fuera de ella el mensaje de bsqueda fallida. Como puede verse, esta adaptacin del programa solo exige muy pequeas modificaciones. #include <iostream.h> // rbol binario con bsqueda (II)
struct base { char let; struct base* izq; struct base* der; } *rz, *aptr;
// Estructura a utilizar
char previo, ant; // globales auxiliares int incluir(char letra, struct base* puntero); void inorden (struct base* puntero); char acepta (void); // aceptar datos del teclado void busca(char key, struct base* puntero); // buscar void nodo(struct base* puntero); // mostrar resultado de busqueda int main(void) { // ========================== char c; if ((rz = new(base)) == NULL) { // crear nodo raz cout << "NO queda memoria" << endl; return 1; } rz->let = '\\'; // carcter en el nodo raz rz->izq = rz->der = NULL; while ( (c = acepta()) != 27) { // Bucle principal if (c == '?') { previo = c; continue; } else if (previo == '?') { previo = c; try { busca(c, rz); } // bloque try (buscar) catch (struct base* ptr) { nodo(ptr); continue; } cout << "No encontrado\a" << endl; continue; } else if (incluir(c, rz)) break; inorden(rz); } } char acepta (void) { // Introducir datos por teclado char c; cout << "\n Pulse un caracter + [CR] "; while (1) { c = getchar(); if (c == 10) continue; // 10 == New Line if (c >= 65 && c <= 91) return c; if (c >= 97 && c <= 123 ) return c; if (c == 27 || c == '?') return c; cout << "\a"; } } int incluir(char letr, struct base* ptr) { if (letr == ptr->let) return 0; if (letr < ptr->let) { // aadir elemento // El carcter ya existe
if (ptr->izq == NULL) { // enlace libre: incluir aptr = (struct base*) malloc(sizeof(base)); if (aptr == NULL) { cout << "NO queda memoria" << endl; return 1; } aptr->let = letr; aptr->izq = aptr->der = NULL; ptr->izq = aptr; return 0; } if (incluir(letr, ptr->izq)) return 1; // falla la insercin } if (letr > ptr->let) { if (ptr->der == NULL) { // enlace libre: incluir aptr = (struct base*) malloc(sizeof(base)); if (aptr == NULL) { cout << "NO queda memoria" << endl; return 1; } aptr->let = letr; aptr->izq = aptr->der = NULL; ptr->der = aptr; return 0; } if (incluir(letr, ptr->der)) return 1; // falla la insercin } return 0; } void inorden (struct base * ptr) { if (ptr == NULL) return; inorden(ptr->izq); cout << " - " << ptr->let; inorden(ptr->der); } // Recorrer rbol
void busca(char key, struct base* ptr) { // buscar key if (key == ptr->let) { throw(ptr); } // lanzar excepcion ant = ptr->let; if (key < ptr->let) { // debe estar en rama izquierda if (ptr->izq == NULL) return; // no existe busca(key, ptr->izq); // seguir bsqueda } if (key > ptr->let) { // debe estar en rama derecha if (ptr->der == NULL) return; // no existe busca(key, ptr->der); // seguir bsqueda } return; } void nodo(struct base* ptr) { // mostrar resultado char izq = '#', der = '#', key = ptr->let; if (ptr->izq != NULL) izq = ptr->izq->let; // letra nodo izq. if (ptr->der != NULL) der = ptr->der->let; // letra nodo der. cout << "\n " << ant << endl;
" |" << endl; " " << key << endl; "/ \\" << endl; izq << " " << der << endl;