Version:0.9 StartHTML:0000000105 EndHTML:0000039743 StartFragment:0000000152 EndFragment:0000039709
/******************************************************/
/*************** Isidro Pastor Jorda ******************/
/******************************************************/
/****************** Telematica ************************/
/******************** FPII ****************************/
/****************** Practica 6 ************************/
/******************************************************/
#include <iostream.h>
#include <stdlib.h>
#include <math.h>
#include "Pila.h"
#include "ArbolBinario.h"
#include <conio.c>
void Introducir(Pila &postfija, Valor &expresion);
int Prioridad(Valor op);
bool EsOperador(char aux);
void ArbolExpresion(Pila &Expresion, Arbol &arb);
int Evaluar(Arbol &a);
Valor Ensamblador(Arbol &a, int &i);
bool ArbolLleno(Arbol & a);
int ContarNodos(Arbol & a);
int Altura(Arbol & a);
int ContarHojas(Arbol & a);
int NodosInternos(Arbol & a);
void VerPrefija(Arbol & a);
void VerPostfija(Arbol & a);
void VerInfija(Arbol & a);
int main()
{
Valor expresion;
Pila postfija;
Arbol arb;
bool salir, salir_arbol;
salir = false;
int opcion, i;
clrscr();
cout << " Programa Practica 6 FP2 ITT Telematica \n";
cout << " Isidro Pastor Jorda\n";
while (!salir)
{
cout << "***********************Menu***********************" << endl;
cout << "1.Introducir la expresion:" << endl;
cout << "2.Visualizar en notacion prefija." << endl;
cout << "3.Visualizar en notacion infija." << endl;
cout << "4.Visualizar en notacion postfija." << endl;
cout << "5.Evaluar la expresion y mostrar el resultado" << endl;
cout << "6.Generar codigo emsamblador" << endl;
cout << "7.Menu arbol:" << endl;
cout << "8. Salir " << endl;
cout << "**************************************************" << endl;
cout << " Opcion -> ";
cin >> opcion;
switch (opcion)
{
case 1:
Introducir(postfija, expresion);
cout << " La expresion es -> " << expresion << endl;
ArbolExpresion(postfija,arb);
break;
case 2:
cout << " La expresion en notacion prefija es ";
VerPrefija(arb);
cout << endl;
break;
case 3:
cout << " La expresion en notacion infija es ";
VerInfija(arb);
cout << endl;
break;
case 4:
cout << " La expresion en notacion postfija es ";
VerPostfija(arb);
cout << endl;
break;
case 5:
cout << " Evaluacion de la expresion: " << expresion << " = " << Evaluar(arb) << endl;
break;
case 6:
i=0;
cout << " El codigo ensamblador generado es:" << endl;
Ensamblador(arb,i);
break;
case 7:
while (!salir_arbol)
{
clrscr(); // Borramos la pantalla
cout << " ********** Menu Arbol *******************" << endl;
cout << " 1. Altura del arbol" << endl;
cout << " 2. Numero de hojas del arbol" << endl;
cout << " 3. Numero de nodos del arbol" << endl;
cout << " 4. Numero de nodos internos del arbol" << endl;
cout << " 5. Verificacion de arbol lleno" << endl;
cout << " 6. Volver al Menu Principal " << endl;
cout << " *****************************************" << endl;
cout << " Elige opcion -> ";
cin >> opcion;
switch (opcion)
{
case 1:
cout << "La altura del arbol es: " << Altura(arb) << endl;
break;
case 2:
cout << "El arbol tiene " << ContarHojas(arb) << " hojas" << endl;
break;
case 3:
cout << "El arbol tiene " << ContarNodos(arb) << " nodos" << endl;
break;
case 4:
cout << "El arbol tiene " << NodosInternos(arb) << " nodos internos" << endl;
break;
case 5:
if(ArbolLleno(arb))
cout << "El arbol esta lleno." << endl;
else
cout << "El arbol no esta lleno." << endl;
break;
case 6:
salir_arbol = true;
break;
default:
cerr << "Opcion no valida";
break;
} // switch menu arbol
if (opcion != 6) // condicional para que no desaparezca la pantalla sin ver resultados
{
cin.ignore();
cout << " Pulsa return para continuar .... ";
cin.get();
}
}// while menu arbol
salir_arbol = false;
break;
case 8:
salir = true;
break;
default:
cerr << " Opcion no valida " << endl;
break;
}
if (!salir) // condicional para que no desaparezca la pantalla sin ver resultados
{
if (opcion != 1) // si hemos introducido una expresion el ignore lo hemos hecho antes
cin.ignore();
cout << " Pulsa return para continuar .... ";
cin.get();
}
clrscr();
} // while (!salir)
return 0;
};
/*****************************************************************************
* Funcion: Introducir
* Descripcion: Pedira al usuario que introduzca una expresion para introducirla
* en una pila en notacion postfija
*
*
*
* Parametros:
*
* Nombre E/S Descripcion
* ------ ----- -----------
* postfija E/S Pila donde tendremos la expresion ordenada postfija
* expresion E/S Expresion introducida por el usuario para usarla en el programa principal
*
*
* Valor devuelto:
* No devuelve nada, void, pero modifica la pila y la expresion
*****************************************************************************/
void Introducir(Pila &postfija, Valor &expresion)
{
Pila b;
int i = 0;
Valor op, optop, num;
cin.ignore(); // Vaciamos el buffer para que podamos leer correctamente la expresion por si acaso
cout << "Introduce la expresion -> " ;
getline(cin, expresion);
while(expresion.find(' ')!= -1) // quitamos los espacios en blanco de la expresion
expresion.erase(expresion.find(' '),1);
while(i < expresion.length())
{
if (!EsOperador(expresion[i]) ) // si el caracter no es un operador
{ while(!EsOperador(expresion[i]) && (i < expresion.length()))// tendremos un numero mientras no sea operador y estemos dentro del string
{
num = num + expresion[i]; // vamos aņadiendo caracteres al numero
i++; // avanzamos el indice del string
}
postfija.Apilar(num); // apilamos en la pila postfija
num = ""; // reinicializamos el valor num para capturar nuevos numeros
}
else // Si el caracter leido no es un numero
{
op=expresion[i]; // almacenamos el caracter en op
b.CimaPila(optop); // leemos la cima de nuestra pila auxiliar
while(!b.PilaVacia() && (Prioridad(optop) >= Prioridad(op))) // si no es vacia y tiene mas prioridad la cima de pila
{
b.Desapilar(); // desapilamos de la pila auxiliar
postfija.Apilar(optop); // apilamos el operador en la pila postfija
b.CimaPila(optop); // y volvemos a leer la cima de la pila para seguir comparando
}
b.Apilar(op); // al final apilamos el dato leido del string
i++; // y aumentamos el indice del string
} // else
} // while
while (!b.PilaVacia()) // para finalizar desapilamos todo el contenido de la pila auxiliar
{
b.CimaPila(optop);
postfija.Apilar(optop); // y lo vamos apilando en la pila postfija
b.Desapilar();
}
return;
};
/*****************************************************************************
* Funcion: Prioridad
* Descripcion: Evaluacion de la prioridad de un operador
*
*
*
* Parametros:
*
* Nombre E/S Descripcion
* ------ ----- -----------
* op E Operador del cual queremos saber la prioridad
*
*
*
* Valor devuelto:
* Un entero que sera la prioridad de ese operador
*****************************************************************************/
int Prioridad(Valor op)
{
int aux;
switch( int(op[0]) ) // asignamos una prioridad a los operadores
{
case 43:
case 45:
aux = 1;
break;
case 42:
case 47:
aux = 2;
break;
case 94:
aux = 3;
break;
default:
aux = 0;
break;
}
return(aux);
};
/*****************************************************************************
* Funcion: EsOperador
* Descripcion: Indica si el caracter pasado por valor es un operador o no
*
*
*
* Parametros:
*
* Nombre E/S Descripcion
* ------ ----- -----------
* aux E Caracter que queremos identificar como operador o no
*
*
*
* Valor devuelto:
* true si el caracter es un operador, false en caso contrario
*****************************************************************************/
bool EsOperador(char aux)
{
bool ok;
/***************************************************************************
* si el caracter leido esta dentro del rango de numeros ascii comprendidos*
* 0 y 9 entonces entenderemos que NO es un operador, en caso contrario *
* consideraremos que el caracter es un operador *
***************************************************************************/
if( ( int(aux) >= int('0') ) && ( int(aux) <= int('9') ))
ok = false;
else
ok = true;
return(ok);
};
/*****************************************************************************
* Funcion: ArbolExpresion
* Descripcion: Pasa los datos de una pila que contiene una expresion en notacion
* postfija a un arbol binario para su mejor tratamiento
*
*
*
* Parametros:
*
* Nombre E/S Descripcion
* ------ ----- -----------
* Expresion E/S Pila que contiene nuestra expresion en postfija
* arb E/S arbol que contendra la expresion
*
*
* Valor devuelto:
* Void, la funcion no devuelve en si ningun valor
*****************************************************************************/
void ArbolExpresion(Pila &Expresion, Arbol &arb)
{
Arbol i, d;
Valor s;
if ( !Expresion.PilaVacia())
{
Expresion.CimaPila(s); // iremos desapilando la pila para ir introduciendo los elementos en el arbol
Expresion.Desapilar();
if (EsOperador(s[0]))
{
ArbolExpresion(Expresion, d);
ArbolExpresion(Expresion, i);
}
arb.HacerArbol(i,s,d);
}
return;
};
/*****************************************************************************
* Funcion: Evaluar
* Descripcion: Evalua una expresion almacenada en un arbol binario
* realizando las operaciones necesarias para obtener el resultado
*
*
*
* Parametros:
*
* Nombre E/S Descripcion
* ------ ----- -----------
* a E/S Arbol que contiene la expresion que queremos evaluar
*
*
*
* Valor devuelto:
* Devuelve un entero que sera el resultado de la expresion evaluada
*****************************************************************************/
int Evaluar(Arbol &a)
{
int aux = 0;
Valor x, operador;
int i; // contador
int op1, op2; //Variables auxiliares para almacenar resultados intermedios
if(!a.ArbolVacio())
{
if( a.HijoIzdo().ArbolVacio() && a.HijoDcho().ArbolVacio() )
{
a.Informacion(x);
i = 0;
while(i < x.length())
{
aux = aux + (int(x[i]) - int('0')); // pasamos a entero el char del numero leido
i++;
if(i < x.length())
aux = aux * 10; // si tenemos mas de un digito para el numero multiplicamos por 10 lo anterior
} //while
} //if
else
{
op1 = Evaluar(a.HijoIzdo()); // op1 sera el resultado de evaluar el hijo izquierdo recursivamente
op2 = Evaluar(a.HijoDcho()); // op2 sera el resultado de evaluar el hijo derecho recursivamente
a.Informacion(operador);
switch(int(operador[0])) // segun que operador sea haremos una operacion diferente
{
case 43:
aux = op1 + op2;
break;
case 45:
aux = op1 - op2;
break;
case 42:
aux = op1 * op2;
break;
case 47:
if (op2 == 0 )
cout << " Division por Cero, No se puede evaluar correctamente la expresion\n";
else
aux = op1 / op2;
break;
case 94:
aux = int (pow(op1, op2));
break;
default:
cerr << " Error de Operador no Reconocido -> " << operador << endl;
break;
}//switch
}//else
}// if(!a.ArbolVacio())
return(aux);
};
/*****************************************************************************
* Funcion: Ensamblador
* Descripcion: Genera y muestra por pantalla el codigo ensamblador de las
* operaciones que se deben realizar para evaluar la expresion
*
*
*
* Parametros:
*
* Nombre E/S Descripcion
* ------ ----- -----------
*
*
*
*
* Valor devuelto:
* Devolvera un Valor que sera el resultado de evaluar cada nodo del arbol
*****************************************************************************/
Valor Ensamblador(Arbol &a, int &i)
{
Valor aux, aux1, aux2, operador;
if (!a.ArbolVacio())
{
if ( ( ( a.HijoIzdo() ).ArbolVacio()) && ( ( a.HijoDcho() ).ArbolVacio() ) )
a.Informacion(aux);
else // cuando son nodos internos siempre tenemos operadores
{
aux1 = Ensamblador(a.HijoIzdo(), i);
aux2 = Ensamblador(a.HijoDcho(), i);
a.Informacion(operador);
i++;
cout.setf(ios::left);
cout.width (7);
switch (int(operador[0]))
{
case 43:
cout << "add \t \t";
break;
case 45:
cout << "sub \t \t";
break;
case 42:
cout << "mul \t \t";
break;
case 47:
cout << "div \t \t";
break;
case 94:
cout << "pow \t \t" ;
break;
default:
cerr << "error \t \t";
break;
}
cout << aux1 << "\t \t" << aux2 << "\t \t";
aux="temp";
aux= aux + char(48+i); // generamos una variable aleatoria para almacenar un resultado temporal
/************************************************************************
* Solo usamos 9 variables temporales, si se requieren mas se reutilizan*
* las variables empezando de nuevo por la 1 *
***********************************************************************/
if (i == 9) // iniciamos a cero de nuevo el valor de i cuando llevamos a 9
i = 0;
cout << aux << endl;
} // else
}
return (aux);
};
/*****************************************************************************
* Funcion: ArbolLleno
* Descripcion: La funcion comprueba si el arbol esta lleno
*
*
*
* Parametros:
*
* Nombre E/S Descripcion
* ------ ----- -----------
* a E/S Arbol del que queremos saber si esta lleno o no
*
*
*
* Valor devuelto:
* true si el arbol esta lleno, false en caso contrario
*****************************************************************************/
bool ArbolLleno(Arbol & a)
{
int nodos, alt;
bool lleno;
nodos = ContarNodos(a);
alt = Altura(a);
lleno = (nodos == ( pow(2,alt) - 1 )); // 2^altura menos 1 son los nodos totales de un arbol
return (lleno);
};
/*****************************************************************************
* Funcion: ContarNodos
* Descripcion: Cuenta los nodos de un arbol
*
*
*
* Parametros:
*
* Nombre E/S Descripcion
* ------ ----- -----------
* a E/S arbol del cual queremos contar los nodos
*
*
*
* Valor devuelto:
* Numero entero correspondiente al numero de nodos del arbol
*****************************************************************************/
int ContarNodos(Arbol & a)
{
int nodos = 0;
if (a.ArbolVacio()) // si el arbol es vacio tiene 0 nodos
nodos = 0;
else // si el arbol no es vacio contaremos los nodos del hijo izdo y del dcho + 1
{
nodos = nodos + ContarNodos(a.HijoIzdo());
nodos = nodos + ContarNodos(a.HijoDcho());
nodos++;
}
return (nodos);
};
/*****************************************************************************
* Funcion: Altura
* Descripcion: Funcion que calcula la altura de un arbol (numero de niveles)
*
*
*
* Parametros:
*
* Nombre E/S Descripcion
* ------ ----- -----------
* a E/S Arbol del que queremos saber la altura
*
*
*
* Valor devuelto:
* Numero entero correspondiente a la altura del arbol
*****************************************************************************/
int Altura(Arbol & a)
{
int alt;
int der, izq;
if (a.ArbolVacio())
alt = 0;
else
{
izq = Altura (a.HijoIzdo());
der = Altura (a.HijoDcho());
if (izq > der)
alt = izq + 1;
else
alt = der + 1;
}
return (alt);
};
/*****************************************************************************
* Funcion: ContarHojas
* Descripcion: Cuenta las hojas o nodos terminales de un arbol
*
*
*
* Parametros:
*
* Nombre E/S Descripcion
* ------ ----- -----------
* a E/S Arbol del que queremos contar las hojas
*
*
*
* Valor devuelto:
* Entero correspondiente al numero de hojas que tiene el arbol
*****************************************************************************/
int ContarHojas(Arbol & a)
{
int n_hojas = 0;
if (a.ArbolVacio())
n_hojas=0; // si el arbol es vacio no tenemos hojas
else
{
if ( (a.HijoIzdo().ArbolVacio()) && ( a.HijoDcho().ArbolVacio() ) )
n_hojas = 1; // si los dos hijos del arbol son vacios eso sera una hoja
else
n_hojas = ContarHojas(a.HijoIzdo()) + ContarHojas(a.HijoDcho()); // si el nodo no es vacio contamos y sumamos las hojas de sus hijos
}
return (n_hojas);
};
/*****************************************************************************
* Funcion: NodosInternos
* Descripcion: Funcion que cuenta los nodos internos de un arbol
*
*
*
* Parametros:
*
* Nombre E/S Descripcion
* ------ ----- -----------
* a E/S Arbol del cual queremos contar los nodos internos
*
*
*
* Valor devuelto:
* Entero correspondiente a los nodos internos del arbol
*****************************************************************************/
int NodosInternos(Arbol & a)
{
int nodos, hojas;
nodos = ContarNodos(a);
hojas = ContarHojas(a);
return ( nodos - hojas ); // los nodos internos seran los nodos totales menos las hojas
};
/*****************************************************************************
* Funcion: VerPrefija
* Descripcion: Funcion que recorre el arbol de forma prefija y muestra el
* contenido de cada nodo de esta forma
*
*
*
* Parametros:
*
* Nombre E/S Descripcion
* ------ ----- -----------
* a E/S Arbol que queremos visualizar
*
*
*
* Valor devuelto:
* No devuelve ningun valor, void, simplemente muestra el contenido por pantalla
*****************************************************************************/
void VerPrefija(Arbol &a)
{
Valor x;
if (!a.ArbolVacio())
{
a.Informacion(x); // mostramos el nodo raiz
cout << x << " ";
VerPrefija(a.HijoIzdo()); // y despues hijo izquierdo
VerPrefija(a.HijoDcho()); // seguido del hijo derecho
}
return;
};
/*****************************************************************************
* Funcion: VerPostfija
* Descripcion: Funcion que recorre el arbol de forma Postfija y muestra el
* contenido de cada nodo de esta forma
*
*
*
* Parametros:
*
* Nombre E/S Descripcion
* ------ ----- -----------
* a E/S Arbol que queremos visualizar
*
*
*
* Valor devuelto:
* No devuelve ningun valor, void, simplemente muestra el contenido por pantalla
*****************************************************************************/
void VerPostfija(Arbol & a)
{
Valor x;
if (!a.ArbolVacio())
{
VerPostfija(a.HijoIzdo()); // mostramos primero el contenido del hijo izquierdo
VerPostfija(a.HijoDcho()); // despues el derecho
a.Informacion(x); // y finalmente el nodo raiz
cout << x << " ";
}
return;
};
/*****************************************************************************
* Funcion: VerInfija
* Descripcion: Funcion que recorre el arbol de forma Infija y muestra el
* contenido de cada nodo de esta forma
*
*
*
* Parametros:
*
* Nombre E/S Descripcion
* ------ ----- -----------
* a E/S Arbol que queremos visualizar
*
*
*
* Valor devuelto:
* No devuelve ningun valor, void, simplemente muestra el contenido por pantalla
*****************************************************************************/
void VerInfija(Arbol & a)
{
Valor x;
if (!a.ArbolVacio())
{
VerInfija(a.HijoIzdo()); // mostramos primero el contenido del hijo izquierdo
a.Informacion(x); // despues el contenido del nodo raiz
cout << x << " ";
VerInfija(a.HijoDcho()); // y finalmente el contenido del hijo derecho
}
return;
};