Arboles

43
Arboles en Java: Recorrido Preorden, Inorden y Postorden El recorrido de árboles refiere al proceso de visitar de una manera sistemática, exactamente una vez, cada nodo en una estructura de datos de árbol (examinando y/o actualizando los datos en los nodos). Preorden: (raíz, izquierdo, derecho). Para recorrer un árbol binario no vacío en preorden, hay que realizar las siguientes operaciones recursivamente en cada nodo, comenzando con el nodo de raíz: 1. Visite la raíz 2. Atraviese el sub-árbol izquierdo 3. Atraviese el sub-árbol derecho Inorden: (izquierdo, raíz, derecho). Para recorrer un árbol binario no vacío en inorden (simétrico), hay que realizar las siguientes operaciones recursivamente en cada nodo: 1. Atraviese el sub-árbol izquierdo 2. Visite la raíz 3. Atraviese el sub-árbol derecho Postorden: (izquierdo, derecho, raíz). Para recorrer un árbol binario no vacío en postorden, hay que realizar las siguientes operaciones recursivamente en cada nodo: 1. Atraviese el sub-árbol izquierdo 2. Atraviese el sub-árbol derecho 3. Visite la raíz En general, la diferencia entre preorden, inorden y postorden es cuándo se recorre la raíz. En los tres, se recorre primero el sub-árbol izquierdo y luego el derecho. En preorden, la raíz se recorre antes que los recorridos de los subárboles izquierdo y derecho

Transcript of Arboles

Page 1: Arboles

Arboles en Java: Recorrido Preorden, Inorden y Postorden

El recorrido de árboles refiere al proceso de visitar de una manera sistemática, exactamente una vez, cada nodo en una estructura de datos de árbol (examinando y/o actualizando los datos en los nodos).

Preorden: (raíz, izquierdo, derecho). Para recorrer un árbol binario no vacío en preorden, hay que realizar las siguientes operaciones recursivamente en cada nodo, comenzando con el nodo de raíz:

1. Visite la raíz2. Atraviese el sub-árbol izquierdo3. Atraviese el sub-árbol derecho

Inorden: (izquierdo, raíz, derecho). Para recorrer un árbol binario no vacío en inorden (simétrico), hay que realizar las siguientes operaciones recursivamente en cada nodo:

1. Atraviese el sub-árbol izquierdo2. Visite la raíz3. Atraviese el sub-árbol derecho

Postorden: (izquierdo, derecho, raíz). Para recorrer un árbol binario no vacío en postorden, hay que realizar las siguientes operaciones recursivamente en cada nodo:

1. Atraviese el sub-árbol izquierdo2. Atraviese el sub-árbol derecho3. Visite la raíz

En general, la diferencia entre preorden, inorden y postorden es cuándo se recorre la raíz. En los tres, se recorre primero el sub-árbol izquierdo y luego el derecho.

En preorden, la raíz se recorre antes que los recorridos de los subárboles izquierdo y derecho

En inorden, la raíz se recorre entre los recorridos de los árboles izquierdo y derecho, y

En postorden, la raíz se recorre después de los recorridos por el subárbol izquierdo y el derecho

?123456

public class NodoArbol{    //miembros de acceso    NodoArbol nodoizquierdo;    int datos;    NodoArbol nododerecho;

    //iniciar dato y hacer de este nodo un nodo hoja

Page 2: Arboles

7891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253

    public NodoArbol(int datosNodo)    {        datos = datosNodo;        nodoizquierdo = nododerecho = null; //el nodo no tiene hijos    }

    //buscar punto de insercion e inserter nodo nuevo    public synchronized void insertar(int valorInsertar)    {        //insertar en subarbol izquierdo        if(valorInsertar < datos)        {            //insertar en subarbol izquierdo            if(nodoizquierdo == null)                nodoizquierdo = new NodoArbol(valorInsertar);            else    //continua recorriendo subarbol izquierdo                nodoizquierdo.insertar(valorInsertar);        }

        //insertar nodo derecho        else if(valorInsertar > datos)        {            //insertar nuevo nodoArbol            if(nododerecho == null)                nododerecho = new NodoArbol(valorInsertar);            else                nododerecho.insertar(valorInsertar);        }    } // fin del metodo insertar}

class Arbol{    private NodoArbol raiz;

    //construir un arbol vacio    public Arbol()    {        raiz = null;    }

    //insertar un nuevo ndo en el arbol de busqueda binaria    public synchronized void insertarNodo(int valorInsertar)    {        if(raiz == null)            raiz = new NodoArbol(valorInsertar); //crea nodo raiz        else            raiz.insertar(valorInsertar); //llama al metodo insertar    }

    // EMPIEZA EL RECORRIDO EN PREORDEN    public synchronized void recorridoPreorden()    {        ayudantePreorden(raiz);    }    //meoto recursivo para recorrido en preorden

Page 3: Arboles

5455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910

    private void ayudantePreorden(NodoArbol nodo)    {        if(nodo == null)            return;

        System.out.print(nodo.datos + " ");     //mostrar datos del nodo        ayudantePreorden(nodo.nodoizquierdo);   //recorre subarbol izquierdo        ayudantePreorden(nodo.nododerecho);     //recorre subarbol derecho    }

    //EMPEZAR RECORRIDO INORDEN    public synchronized void recorridoInorden()    {        ayudanteInorden(raiz);    }

    //meoto recursivo para recorrido inorden    private void ayudanteInorden( NodoArbol nodo)    {        if(nodo == null)            return;

        ayudanteInorden(nodo.nodoizquierdo);        System.out.print(nodo.datos + " ");        ayudanteInorden(nodo.nododerecho);    }

    //EMPEZAR RECORRIDO PORORDEN    public synchronized void recorridoPosorden()    {        ayudantePosorden(raiz);    }

    //meotod recursivo para recorrido posorden    private void ayudantePosorden(NodoArbol nodo)    {        if( nodo == null )            return;

        ayudantePosorden(nodo.nodoizquierdo);        ayudantePosorden(nodo.nododerecho);        System.out.print(nodo.datos + " ");    }}

Page 4: Arboles

0101102103104105106107108109

Clase controladora: ?12345678910111213141516171819202122232425

import javax.swing.JOptionPane;

public class PruebaArbol{    public static void main(String args [])    {        Arbol arbol = new Arbol();        int valor;        String Dato;

        System.out.println("Insertando los siguientes valores: ");

        Dato = JOptionPane.showInputDialog("Inserta el numero de nodos que desea ingresar");        int n = Integer.parseInt(Dato);

        for(int i = 1; i <= n; i++ )        {            Dato = JOptionPane.showInputDialog("Dame el " + i + " valor para colocar en el Arbol");            valor = Integer.parseInt(Dato);            System.out.print(valor + " ");            arbol.insertarNodo(valor);        }

        System.out.println("\n\nRecorrido Preorden");        arbol.recorridoPreorden();

        System.out.println("\n\nRecorrido Inorden");        arbol.recorridoInorden();

Page 5: Arboles

2627282930313233

        System.out.println("\n\nRecorrido Postorden");        arbol.recorridoPosorden();    }}

Output:Insertando los siguientes valores:35 50 8 12 69 84 25 75 93 16

Recorrido Preorden35 8 12 25 16 50 69 84 75 93

Recorrido Inorden8 12 16 25 35 50 69 75 84 93

Recorrido Postorden16 25 12 8 75 93 84 69 50 35

Aplicaciones de árboles binarios

Un árbol binario es una estructura de datos útil cuando se trata de hacer modelos de procesos en donde se requiere tomar decisiones en uno de dos sentidos en cada parte del proceso. Por ejemplo, supongamos que tenemos un arreglo en donde queremos encontrar todos los duplicados. Esta situación es bastante útil en el manejo de las bases de datos, para evitar un problema que se llama redundancia.

Una manera de encontrar los elementos duplicados en un arreglo es recorrer todo el arreglo y comparar con cada uno de los elementos del arreglo. Esto implica que si el arreglo tiene

elementos, se deben hacer comparaciones, claro, no es mucho problema si es un número pequeño, pero el problema se va complicando más a medida que aumenta.

Si usamos un árbol binario, el número de comparaciones se reduce bastante, veamos cómo.

Page 6: Arboles

El primer número del arreglo se coloca en la raíz del árbol (como en este ejemplo siempre vamos a trabajar con árboles binarios, simplemente diremos árbol, para referirnos a un árbol binario) con sus subárboles izquierdo y derecho vacíos. Luego, cada elemento del arreglo se compara son la información del nodo raíz y se crean los nuevos hijos con el siguiente criterio:

Si el elemento del arreglo es igual que la información del nodo raíz, entonces notificar duplicidad.

Si el elemento del arreglo es menor que la información del nodo raíz, entonces se crea un hijo izquierdo.

Si el elemento del arreglo es mayor que la información del nodo raíz, entonces se crea un hijo derecho.

Una vez que ya está creado el árbol, se pueden buscar los elementos repetidos. Si x el elemento buscado, se debe recorrer el árbol del siguiente modo:

Sea k la información del nodo actual p. Si entonces cambiar el nodo actual a right(p), en caso contrario, en caso de que informar una ocurrencia duplicada y en

caso de que cambiar el nodo actual a left(p).

El siguiente algoritmo

leer numero buscado >> ntree=makeTree(n)while(hay numeros en el arreglo){ leeSiguienteNumero >> k p=q=tree; while(k!=info(p)&&q!=NULL){ p=q if(k<info(p)) q=left(p) else q=right(p) } if(k==info(p)) despliega<<" el numero es duplicado"; else if (k<info(p)) setLeft(p,k) else setRight(p,k) }

Page 7: Arboles

Figura 28: Árbol binario para encontrar números duplicados

Para saber el contenido de todos los nodos en un árbol es necesario recorrer el árbol. Esto es debido a que solo tenemos conocimiento del contenido de la dirección de un nodo a la vez. Al recorrer el árbol es necesario tener la dirección de cada nodo, no necesariamente todos al mismo tiempo, de hecho normalmente se tiene la dirección de uno o dos nodos a la vez; de manera que cuando se tiene la dirección de un nodo, se dice que se visita ese nodo.

Aunque hay un orden preestablecido (la enumeración de los nodos) no siempre es bueno recorrer el árbol en ese orden, porque el manejo de los apuntadores se vuelve más complejo. En su lugar se han adoptado tres criterios principales para recorrer un árbol binario, sin que de omita cualquier otro criterio diferente.

Los tres criterios principales para recorrer un árbol binario y visitar todos sus nodos son, recorrer el árbol en:

preorden:Se ejecutan las operaciones:

1. Visitar la raíz 2. recorrer el subárbol izquierdo en preorden 3. recorrer el subárbol derecho en preorden

entreorden:Se ejecutan las operaciones:

1. recorrer el subárbol izquierdo en entreorden 2. Visitar la raíz 3. recorrer el subárbol derecho en entreorden

postorden:Se ejecutan las operaciones:

1. recorrer el subárbol izquierdo en postorden 2. recorrer el subárbol derecho en postorden 3. Visitar la raíz

Page 8: Arboles

Al considerar el árbol binario que se muestra en la figura 28 usando cada uno de los tres criterios para recorrer el árbol se tienen las siguientes secuencias de nodos:

En preorden:

En entreorden:

En postorden:

Esto nos lleva a pensar en otra aplicación, el ordenamiento de los elementos de un arreglo.

Para ordenar los elementos de un arreglo en sentido ascendente, se debe construir un árbol similar al árbol binario de búsqueda, pero sin omitir las coincidencias.

El arreglo usado para crear el árbol binario de búsqueda fue

<14,15,4,9,7,18,3,5,16,4,20,17,9,14,5>

El árbol de ordenamiento es el que se muestra en la figura 29

Figura 29: Árbol binario para ordenar una secuencia de números

Para ordenar los elementos de este arreglo basta recorrer el árbol en forma de entreorden.

¿Cuál sería el algoritmo para ordenarlo de manera descendente?

Ejemplo sencillo de árbol de búsqueda binario en JAVAimport java.io.*;

Page 9: Arboles

class NodoBinario{

int dato;

NodoBinario Hizq, Hder;

//Constructores

NodoBinario (int Elem){

dato = Elem;

NodoBinario Hizq, Hder = null;

}

//Insercion de un elemento

public void InsertaBinario (int Elem){

if(Elem < dato){

if (Hizq == null)

Hizq = new NodoBinario(Elem);

else

Hizq.InsertaBinario(Elem);

}

else{

if (Elem > dato){

if (Hder == null)

Hder = new NodoBinario (Elem);

else

Hder.InsertaBinario(Elem);

}

}

}

}

Page 10: Arboles

//Definicion de la clase Arbol

class Arbol{

Cola Cola = new Cola();

NodoBinario Padre;

NodoBinario Raiz;

//Constructor

public Arbol(){

Raiz = null;

}

//Insercion de un elemento en el arbol

public void InsertaNodo(int Elem){

if(Raiz == null)

Raiz = new NodoBinario (Elem);

else

Raiz.InsertaBinario (Elem);

}

//Preorden Recursivo del arbol

public void Preorden (NodoBinario Nodo){

if(Nodo == null)

return;

else{

System.out.print (Nodo.dato + ” “);

Preorden (Nodo.Hizq);

Preorden (Nodo.Hder);

}

}

Page 11: Arboles

//PostOrden recursivo del arbol

public void PostOrden (NodoBinario Nodo){

if(Nodo == null)

return;

else{

PostOrden (Nodo.Hizq);

PostOrden (Nodo.Hder);

System.out.print (Nodo.dato + ” “);

}

}

//Inorden Recursivo del arbol

public void Inorden (NodoBinario Nodo){

if(Nodo == null)

return;

else{

Inorden (Nodo.Hizq);

System.out.print(Nodo.dato + ” “);

Inorden (Nodo.Hder);

}

}

//Busca un elemento en el arbol

void Busqueda (int Elem, NodoBinario A){

if((A == null) | (A.dato == Elem)){

System.out.print(A.dato + ” “);

return;

}

Page 12: Arboles

else{

if(Elem>A.dato)

Busqueda (Elem, A.Hder);

else

Busqueda ( Elem, A.Hizq);

}

}

//Altura del arbol

public int Altura (NodoBinario Nodo){

int Altder = (Nodo.Hder == null? 0:1 + Altura (Nodo.Hder));

int Altizq = (Nodo.Hizq == null? 0:1 + Altura (Nodo.Hizq));

return Math.max(Altder,Altizq);

}

//Recorrido en anchura del arbol

public void Anchura (NodoBinario Nodo){

Cola cola= new Cola();

NodoBinario T = null;

//System.out.print (“El recorrido en Anchura es: “);

if(Nodo != null){

cola.InsertaFinal (Nodo);

while(!(cola.VaciaLista ())){

T = cola.PrimerNodo.datos;

cola.EliminaInicio();

System.out.print(T.dato + ” “);

if (T.Hizq != null)

cola.InsertaFinal (T.Hizq);

Page 13: Arboles

if (T.Hder != null)

cola.InsertaFinal (T.Hder);

}

}

System.out.println();

}

}

//Definición de la Clase NodoLista

class NodosListaA{

NodoBinario datos;

NodosListaA siguiente;

//Construtor Crea un nodo del tipo Object

NodosListaA (NodoBinario valor){

datos =valor;

siguiente = null; //siguiente con valor de nulo

}

// Constructor Crea un nodo del Tipo Object y al siguiente nodo de la lista

NodosListaA (NodoBinario valor, NodosListaA signodo){

datos = valor;

siguiente = signodo; //siguiente se refiere al siguiente nodo

}

}

//Definición de la Clase Lista

class Cola{

NodosListaA PrimerNodo;

NodosListaA UltimoNodo;

Page 14: Arboles

String Nombre;

//Constructor construye una lista vacia con un nombre de List

public Cola(){

this (“Lista”);

}

//Constructor

public Cola (String s){

Nombre = s;

PrimerNodo = UltimoNodo =null;

}

//Retorna True si Lista Vacía

public boolean VaciaLista() {

return PrimerNodo == null;

}

//Inserta un Elemento al Frente de la Lista

public void InsertaInicio (NodoBinario ElemInser){

if(VaciaLista())

PrimerNodo = UltimoNodo = new NodosListaA (ElemInser);

else

PrimerNodo = new NodosListaA (ElemInser, PrimerNodo);

}

//Inserta al Final de la Lista

public void InsertaFinal(NodoBinario ElemInser){

if(VaciaLista())

PrimerNodo = UltimoNodo = new NodosListaA (ElemInser);

else

Page 15: Arboles

UltimoNodo=UltimoNodo.siguiente =new NodosListaA (ElemInser);

}

//Eliminar al Inicio

public void EliminaInicio(){

if(VaciaLista())

System.out.println (“No hay elementos”);

// Restablecer las referencias de PrimerNodo y UltimoNodo

if(PrimerNodo.equals (UltimoNodo))

PrimerNodo = UltimoNodo = null;

else

PrimerNodo = PrimerNodo.siguiente;

}

//Elimina al final

public void EliminaFinal (){

if(VaciaLista())

System.out.println (“No hay elementos”);

// Restablecer las referencias de PrimerNodo y UltimoNodo

if (PrimerNodo.equals (UltimoNodo))

PrimerNodo = UltimoNodo = null;

else{

NodosListaA Actual =PrimerNodo;

while (Actual.siguiente != UltimoNodo)

Actual = Actual.siguiente;

UltimoNodo =Actual;

Actual.siguiente = null;

}

Page 16: Arboles

}

}

public class ArbolBinario{

public static void main (String[]args)throws IOException

{

BufferedReader entrada =new BufferedReader(new InputStreamReader(System.in));

//creando objeto del arbolito xD

Arbol A = new Arbol();

int b;

for(int j=0;j<6;j++)

{

System.out.println(“Ingresa Datos “);

b=Integer.parseInt(entrada.readLine());

A.InsertaNodo (b);

}

System.out.print(” Preorden es: “);

A.Preorden (A.Raiz);

System.out.println();

System.out.print(” Inorden es: “);

A.Inorden (A.Raiz);

System.out.println();

System.out.print(” Postorden es: “);

A.PostOrden (A.Raiz);

System.out.println();

System.out.println(“La altura del arbol es: ” + A.Altura (A.Raiz));

A.Anchura (A.Raiz);

Page 17: Arboles

}

}

Tipos de Árboles

Árboles etiquetados y árboles de expresiones:

Cuando se asocia una etiqueta, o valor, a cada nodo del árbol, a éste se le denomina árbol etiquetado.

La etiqueta de un nodo no es el nombre del nodo, sino que es información que está incluida en el nodo. Es posible cambiar la etiqueta del nodo sin modificar su nombre.

Un caso particular de los árboles etiquetados lo constituyen los árboles de expresiones, utilizados para la representación de expresiones aritméticas. Las reglas para representar una expresión mediante un árbol etiquetado son:

1.- Cada hoja está etiquetada con un operando y sólo consta de ese operando.

2.- Cada nodo interior está etiquetado con un operador.

Ejemplo 1: la expresión a+b se representaría:

n, n1, n2 son los nombres de los nodos cuyas etiquetas se muestran al lado de los nodos correspondientes. La operación a realizar se pone en el nodo raíz y los operandos en los descendientes de éste.

Árboles binarios:

Page 18: Arboles

Es un árbol donde cada nodo tiene como máximo dos hijos.

Árboles multicamino:

Cada nodo tiene un número arbitrario de hijos y se mantiene un orden en él.

Árboles-B:

Formalmente se define un árbol-B de la siguiente manera:

1. Cada página, excepto la raíz, contiene entre n y 2n elementos. Se utilizará m para indicar el número de elementos por página.

2. Cada página, excepto la página raíz y las páginas hojas, tienen entre n+1 y 2n+1 descendientes.

3. La página raíz tiene al menos dos descendientes.

4. Las páginas hojas están todas al mismo nivel.

Árboles-B+:

Los árboles-B+ se han convertido en la técnica más utilizada para la organización de archivos indexados. La principal característica de estos árboles es que todas las claves se encuentran en las hojas (a diferencia de los árboles-B, en que las claves podían estar en las páginas intermedias) y por lo tanto cualquier camino desde la raíz hasta alguna de las claves tienen la misma longitud.

Formalmente se define un árbol-B+ de la siguiente manera:

1. Cada página, excepto la raíz , contiene entre n y 2n elementos.

2. Cada página, excepto la raíz, tiene entre n+1 y 2n+1 descendientes. Se utiliza m para expresar el número de elementos por página.

3. La página raíz tiene al menos dos descendientes.

4. Las páginas hojas están todas al mismo nivel.

5. Todas las claves se encuentran en las páginas hojas.

6. Las claves de las páginas raíz e interiores se utilizan como índices.

Page 20: Arboles

Arbol binario de expresiones c++

kruncher29 de Mayo del 2008

Tengo la clase para tratar este árbol binario implementada (la pego aqui abajo), tengo que hacer una función recursiva para crear un árbol binario de expresiones a través de un string pero no lo consigo.../******************************************/Clase Arbol binario/******************************************/#include <iostream>using namespace std;

#ifndef ARBIN#define ARBIN

template <class T>class arbin {public://constructoras//construye un arbol binario vacioarbin();

//crea un nuevo arbol binario a partir de un elemento y dos arboles binariosarbin(const T & e, const arbin<T> & ai=arbin(), const arbin<T> & ad=arbin());

//modifica un arbin poniendo e como raiz e izqdo y dcho como hijo izquierdo// y derecho respectivamentevoid modificar (const T & e, const arbin<T> & izqdo, const arbin<T> & dcho);

//modica el arbol actual hasta obtener el arbin vaciovoid vaciar();

//Copia el arbol binario actualarbin<T> copiar();

//Devuelve el subarbol izquierdo del árbol, NULL si está vacíoarbin<T> & izquierdo() const;

//Devuelve el subarbol derecho del árbol, NULL si está vacíoarbin<T> & derecho() const;

//Devuelve el elemento de la raizconst T & datoraiz() const;

Page 21: Arboles

T & datoraiz() ;

//Indica si el árbol binario está vaciobool esvacio () const;

//recorre el arbol en preordenvoid preorden() const;

//muestra el arbol en notacion infijavoid notacion_infija(char) const;

//muestra el arbol en notacion infijavoid notacion_funcional() const;

//Comprueba que el arbin es extendidobool esExtendido () const;

private://nodo del arbol binariostruct Nodo {T info;arbin<T> izq;arbin<T> der;

//constructorNodo (T e=T(), arbin<T> iz=arbin(), arbin<T> de=arbin()) {info=e;izq=iz;der=de;}//destructor//~Nodo();};

typedef Nodo * PNodo;PNodo raiz; //puntero a la raiz del árbol binario

};

/******************************************/Main.cpp - Lo que tengo hecho de momento es/******************************************/arbin <char> crear_arbol (char *s, int pos){int tam = strlen (s);int sig=0;

if (es_entero(s[pos]))

Page 22: Arboles

return arbin <char> (s[pos]);

// Al final del arbol binario siempre hay 2 enteros//return arbin <char> (s[pos],crear_arbol(s,pos+1),crear_arbol(s,pos+2));if (es_entero(s[pos+1]))return arbin <char> (s[pos],crear_arbol(s,pos+1),crear_arbol(s,pos+2));else {int y=pos+2;while ((es_entero(s[y])==false) && (y <= tam))y++;while ((es_entero(s[y])==true) && (y <= tam))y++;cout << "y: " << y;return arbin <char> (s[pos],crear_arbol(s,pos+1),crear_arbol(s,y));}}

Me parece que tengo mal todo, no se como plantear la solución, alguna idea? gracias !

Creo que la cabezera correcta de la función deberia ser:arbin <char> crear_arbol (char *s, int &pos){}

pero de momento así no he conseguido nada... Un saludo !

RESPONDER

kruncher29 de Mayo del 2008

/******************************************/Clase Arbol binario COMPLETA/******************************************/#include <iostream>using namespace std;

#ifndef ARBIN#define ARBIN

template <class T>class arbin {public://constructoras

Page 23: Arboles

//construye un arbol binario vacioarbin();

//crea un nuevo arbol binario a partir de un elemento y dos arboles binariosarbin(const T & e, const arbin<T> & ai=arbin(), const arbin<T> & ad=arbin());

//modifica un arbin poniendo e como raiz e izqdo y dcho como hijo izquierdo// y derecho respectivamentevoid modificar (const T & e, const arbin<T> & izqdo, const arbin<T> & dcho);

//modica el arbol actual hasta obtener el arbin vaciovoid vaciar();

//Copia el arbol binario actualarbin<T> copiar();

//Devuelve el subarbol izquierdo del árbol, NULL si está vacíoarbin<T> & izquierdo() const;

//Devuelve el subarbol derecho del árbol, NULL si está vacíoarbin<T> & derecho() const;

//Devuelve el elemento de la raizconst T & datoraiz() const;T & datoraiz() ;

//Indica si el árbol binario está vaciobool esvacio () const;

//recorre el arbol en preordenvoid preorden() const;

//muestra el arbol en notacion infijavoid notacion_infija(char) const;

//muestra el arbol en notacion infijavoid notacion_funcional() const;

//Comprueba que el arbin es extendidobool esExtendido () const;

private://nodo del arbol binario

Page 24: Arboles

struct Nodo {T info;arbin<T> izq;arbin<T> der;

//constructorNodo (T e=T(), arbin<T> iz=arbin(), arbin<T> de=arbin()) {info=e;izq=iz;der=de;}//destructor//~Nodo();};

typedef Nodo * PNodo;PNodo raiz; //puntero a la raiz del árbol binario

};

#endif

//IMPLEMENTACIONES//construye un arbol binario vaciotemplate <class T>arbin<T>::arbin() {raiz=NULL;}

//crea un nuevo arbol binario a partir de un elemento y dos arboles binariostemplate <class T>arbin<T>::arbin(const T & e, const arbin<T> & izqdo, const arbin<T> & decho) {raiz= new Nodo(e, izqdo, decho);}

//modifica un arbin poniendo e como raiz e izqdo y dcho como hijo izquierdo// y derecho respectivamentetemplate <class T>void arbin<T>::modificar (const T & e, const arbin<T> & izqdo, const arbin<T> & dcho) {if (!esvacio()) {raiz->info=e;raiz->izq=izqdo;

Page 25: Arboles

raiz->der=dcho;}else cout << "Error: arbol binario vacio" << endl;}

//modica el arbol actual hasta obtener el arbin vaciotemplate <class T>void arbin<T>::vaciar() {if (!esvacio()) {izquierdo().vaciar();derecho().vaciar();delete raiz;}}

//Copia el arbol binario actualtemplate <class T>arbin<T> arbin<T>::copiar() {arbin i, d ;if (!esvacio()) {if (!izquierdo().esvacio()) i=izquierdo().copiar();if (!derecho().esvacio()) d=derecho().copiar();//raiz=new Nodo(raiz->info, i, d);//return raiz;arbin x (raiz->info, i, d);return x;}}

//Devuelve el subarbol izquierdo del árbol, NULL si está vacíotemplate <class T>arbin<T> & arbin<T>::izquierdo() const {return raiz->izq;}

//Devuelve el subarbol derecho del árbol, NULL si está vacíotemplate <class T>arbin<T> & arbin<T>::derecho() const {return raiz->der;}

//Devuelve el elemento de la raiztemplate <class T>const T & arbin<T>::datoraiz() const {

Page 26: Arboles

return raiz->info;}template <class T>T & arbin<T>::datoraiz() {return raiz->info;}

//Indica si el árbol binario está vaciotemplate <class T>bool arbin<T>::esvacio () const {return (raiz==NULL);}

template <class T>void arbin<T>::preorden() const {if (!esvacio()) {cout << raiz->info << " ";izquierdo().preorden();derecho().preorden();}}

RESPONDER

kruncher

29 de Mayo del

2008

SOLUCION

Ya tengo hecho el programa, gracias por la ayuda. Lo pego por si os interesa.

/********************************************//* arbin.h/********************************************///Clase ARBOL BINARIO//Esta la clase arbol binario recursiva con el nodo dentro

#include <iostream>using namespace std;

#ifndef ARBIN#define ARBIN

template <class T>class arbin {

Page 27: Arboles

public://constructoras//construye un arbol binario vacioarbin();

//crea un nuevo arbol binario a partir de un elemento y dos arboles binariosarbin(const T & e, const arbin<T> & ai=arbin(), const arbin<T> & ad=arbin());

//modifica un arbin poniendo e como raiz e izqdo y dcho como hijo izquierdo// y derecho respectivamentevoid modificar (const T & e, const arbin<T> & izqdo, const arbin<T> & dcho);

//modica el arbol actual hasta obtener el arbin vaciovoid vaciar();

//Copia el arbol binario actualarbin<T> copiar();

//Devuelve el subarbol izquierdo del &#65533;rbol, NULL si est&#65533; vacarbin<T> & izquierdo() const;

//Devuelve el subarbol derecho del &#65533;rbol, NULL si est&#65533; vacarbin<T> & derecho() const;//Devuelve el elemento de la raizconst T & datoraiz() const;T & datoraiz() ;

//Indica si el &#65533;rbol binario est&#65533; vaciobool esvacio () const;

//recorre el arbol en preordenvoid preorden() const;

//muestra el arbol en notacion infijastring notacion_infija() const;

//Comprueba que el arbin es extendidobool esExtendido () const;

private://nodo del arbol binariostruct Nodo {T info;arbin<T> izq;arbin<T> der;

//constructor

Page 28: Arboles

Nodo (T e=T(), arbin<T> iz=arbin(), arbin<T> de=arbin()) {info=e;izq=iz;der=de;}//destructor//~Nodo();};

typedef Nodo * PNodo;PNodo raiz; //puntero a la raiz del &#65533;rbol binario

};#endif

//IMPLEMENTACIONES//construye un arbol binario vaciotemplate <class T>arbin<T>::arbin() {raiz=NULL;}

//crea un nuevo arbol binario a partir de un elemento y dos arboles binariostemplate <class T>arbin<T>::arbin(const T & e, const arbin<T> & izqdo, const arbin<T> & decho) {raiz= new Nodo(e, izqdo, decho);}

//modifica un arbin poniendo e como raiz e izqdo y dcho como hijo izquierdo// y derecho respectivamentetemplate <class T>void arbin<T>::modificar (const T & e, const arbin<T> & izqdo, const arbin<T> & dcho) {if (!esvacio()) {raiz->info=e;raiz->izq=izqdo;raiz->der=dcho;}else cout << "Error: arbol binario vacio" << endl;}//modica el arbol actual hasta obtener el arbin vaciotemplate <class T>void arbin<T>::vaciar() {if (!esvacio()) {izquierdo().vaciar();derecho().vaciar();

Page 29: Arboles

delete raiz;}}

//Copia el arbol binario actualtemplate <class T>arbin<T> arbin<T>::copiar() {arbin i, d ;if (!esvacio()) {if (!izquierdo().esvacio()) i=izquierdo().copiar();if (!derecho().esvacio()) d=derecho().copiar();//raiz=new Nodo(raiz->info, i, d);//return raiz;arbin x (raiz->info, i, d);return x;}}

//Devuelve el subarbol izquierdo del &#65533;rbol, NULL si est&#65533; vactemplate <class T>arbin<T> & arbin<T>::izquierdo() const {return raiz->izq;}

//Devuelve el subarbol derecho del &#65533;rbol, NULL si est&#65533; vactemplate <class T>arbin<T> & arbin<T>::derecho() const {return raiz->der;}//Devuelve el elemento de la raiztemplate <class T>const T & arbin<T>::datoraiz() const {

return raiz->info;}template <class T>T & arbin<T>::datoraiz() {return raiz->info;}

//Indica si el &#65533;rbol binario est&#65533; vaciotemplate <class T>bool arbin<T>::esvacio () const {return (raiz==NULL);}

Page 30: Arboles

template <class T>void arbin<T>::preorden() const {if (!esvacio()) {cout << raiz->info << " ";izquierdo().preorden();derecho().preorden();}}

template <class T>string arbin<T>::notacion_infija()const{string st;if(!esvacio()){if(!izquierdo().esvacio() && !derecho().esvacio())return st="("+izquierdo().notacion_infija()+raiz->info+derecho().notacion_infija()+")";elsereturn st=raiz->info;}}

////////////// OKktemplate <class T>bool arbin<T>::esExtendido() const {bool ext=false;

if(esvacio()) {ext=true;

} else {if((!izquierdo().esvacio()) && (derecho().esvacio()) || ((izquierdo().esvacio())&& (!derecho().esvacio()))) {ext=false;} else {ext=izquierdo().esExtendido();ext=derecho().esExtendido();}}return ext;}

/********************************************//* main.cpp/********************************************/

Page 31: Arboles

#include <iostream>#include "arbin.h"using namespace std;

bool es_entero (char a) {if (a==\'*\' || a==\'/\' || a==\'-\' || a==\'+\')return false;return true;}

float evaluar (const arbin<char> &a) {if (a.izquierdo().esvacio() && a.derecho().esvacio()) {return a.datoraiz() - \'0\';} else {switch (a.datoraiz()) {case \'+\':return (evaluar(a.izquierdo()) + evaluar(a.derecho()));break;case \'-\':return (evaluar(a.izquierdo()) - evaluar(a.derecho()));break;case \'*\':return (evaluar(a.izquierdo()) * evaluar(a.derecho()));break;case \'/\':return (evaluar(a.izquierdo()) / evaluar(a.derecho()));break;}}}

arbin <char> crear_arbol2 (string cadena,int tam, int &pos){arbin<char> izq,der;if (pos<tam) {if (!es_entero(cadena[pos])) {arbin<char> arb(cadena[pos]);pos++;izq = crear_arbol2 (cadena,tam,pos);pos++;der = crear_arbol2 (cadena,tam,pos);arb.modificar(arb.datoraiz(),izq,der);return arb;} else {return arbin<char> (cadena[pos],izq,der);}}}

Page 32: Arboles

void notacion_funcional(const arbin<char> & a){char raiz;if (!a.esvacio()) {raiz=a.datoraiz();switch (raiz) {case \'+\':cout << "suma(";break;case \'-\':cout << "resta(";break;case \'*\':cout << "producto(";break;case \'/\':cout << "division(";break;default:cout << raiz;break;}notacion_funcional(a.izquierdo());if(raiz==\'+\' || raiz==\'*\'|| raiz==\'/\'||raiz==\'-\' )cout << ",";notacion_funcional(a.derecho());}if(raiz==\'+\' || raiz==\'*\'|| raiz==\'/\'||raiz==\'-\' )cout<<")";}

int main () {

string s;arbin <char> a;char sig = \'s\';int tam;

while (sig!=\'n\') {cout << "Nueva cadena: ";cin >> s;tam= s.length();cout << endl;cout << "Longitud: " << tam ;

// PREGUNTA 1//cout << "****************************************" << endl;

Page 33: Arboles

//cout << "Crear arbol: " << endl;int pos =0;a = crear_arbol2 (s,tam,pos);cout << endl;// PREGUNTA 2cout << "****************************************" << endl;cout << "Mostrar arbol: " << endl;a.preorden();cout << endl;

// PREGUNTA 3cout << "****************************************" << endl;if (a.esExtendido())cout << "Es Extendido.";elsecout << "No es Extendido.";cout << endl;

// PREGUNTA 4 Notacion Infijacout << "****************************************" << endl;cout << "Notacion Infija : " << endl;cout << a.notacion_infija();cout << endl;

// PREGUNTA 5cout << "****************************************" << endl;cout << "Notacion funcional: " << endl;notacion_funcional (a);cout << endl;

// PREGUNTA 6cout << "****************************************" << endl;cout << "Evaluar arbol: " << evaluar(a);cout << endl;

////////////////////////////////////////////////////cout << "Introducir otra cadena? (s/n)? ";cin >> sig;cout << endl;

} // Final del while

return 1;}

/********************************************//********************************************/

Page 34: Arboles

/********************************************//********************************************/Esto es todo, para compilar como supongo q ya sabreis ...$ g++ main.cpp && ./a.out

Un saludo !