Salve a tutti, per un corso di Java ho dovuto sviluppare implementazioni di alberi binari e cammini euleriani per attraversarli.
Dal momento che la classe che implementa il cammino euleriano è una classe astratta ne ho anche dovute creare alcune che ne "sovrascrivano" (non riesco a trovare una traduzione migliore di override ) i metodi astratti. Lo scopo di tali classi è di prendere un albero binario che contiene una espressione aritmetica (gli operatori nei nodi interni e gli operandi nelle foglie), calcolarne il risultato e stamparla.

Questa è la classe EulerTour:
codice:
import eccezioni.BoundaryViolationException;
import eccezioni.EmptyTreeException;
import eccezioni.InvalidPositionException;
import interfacce.BinaryTree;
import interfacce.Position;

/**
 * 

Title: EulerTour.java</p>
 *
 * 

Description: implementazione di Euler Tour mediante il template method pattern. Questo consiste nel definire
 * 					un meccanismo di computazione generico che puo' essere specializzato da una particolare applicazione
 * 					ridefinendone alcuni passaggi. L'attraversamento ricorsivo è eseguito dal metodo eulerTour, mentre 
 * 					i metodi ausiliari che eulerTour chiama sono dei "place holders" vuoti. La classe EulerTour è astratta
 * 					e non puo' essere istanziata. Contiene metodi astratti che devono essere specificati nelle sottoclassi
 * 					concrete di EulerTour.</p>
 * 					

EulerTour rappresenta una sorta di unificazione dei diversi metodi di attraversamento di un albero
 * 					visti finora. Mentre questi prevedevano che i nodi venissero visitati al più una volta, l'"
 * 					Euler tour traversal prevede che questo requisito venga rilassato. Il vantaggio è che questo permette
 * 					a algoritmi più generali di essere espressi con facilità. L'attraversamento mediante cammino euleriano 
 * 					di un albero T si puo' vedere informalmente come una "passeggiata" attorno a T, partendo dalla radice verso
 * 					il suo figlio sinistro, e considerando i bordi di T come "muri" da tenere sempre alla propria sinistra.
 * 					Ogni nodo v di T viene incontrato tre volte:
 * 					[/list]
 * 					[*]"Da sinistra" (prima dell'Euler tour del sottoalbero sinistro di v)
 * 					[*]"Dal basso" (tra l'Euler tour dei due sottoalberi di v)
 * 					[*]"Da destra" (dopo l'Euler tour del sottoalbero destro di v)
 * 					[/list]
 * 					Se v è un nodo esterno, le visite avvengono tutte allo stesso momento.</p>
 * 					

Euler tour estende i cocetti di attraversamento inorder, preorder e postorder. L'attraversamento 
 * 					preorder di un albero binario si puo' vedere come un Euler tour traversal tale che ogni nodo ha una azione associata alla 
 * 					visita che viene eseguita solo queno il nodo è incontrato sulla sinistra. Allo stesso modo gli attraversamenti
 * 					inorder e postorder di un albero binario sono equivalenti a Euler tour tali che ogni odo ha una azione associata
 * 					alla visita che viene eseguita solo quando il nodo viene incontrato dal basso o da destra rispettivamente.</p>
 * 
 *
 *
 */

public abstract class EulerTour<E,R> {
	
	protected BinaryTree<E> tree;
	
	/**esegue l'attraversamento; questo metodo astratto deve essere specificato in una sottoclasse concreta
	 * @throws EmptyTreeException */
	public abstract R execute(BinaryTree<E> T) throws EmptyTreeException;
	
	/**inizializza l'attraversamento*/
	protected void init(BinaryTree<E> T) {
		tree = T;
	}
	
	/**Template Method*/
	protected R eulerTour(Position<E> v) {
		TourResult<R> r = new TourResult<R>();
		try {
			visitLeft(v, r); 						//visita da sinistra.
			if (tree.hasLeft(v)) 					//scende al figlio sinistro di v.
				r.left = eulerTour(tree.left(v));	//attraversamento ricorsivo dei figli sinistri di v; salva nel campo left di r i risultati.
			visitBelow(v, r); 						//visita dal basso.
			if (tree.hasRight(v)) 					//scende al figlio destro di v.
				r.right = eulerTour(tree.right(v)); //attraversamento ricorsivo dei figli destri di v; salva nel campo right di r i risultati.
			visitRight(v, r);						//visita da destra.
		
		} catch (InvalidPositionException e) {
			e.printStackTrace();
		} catch (BoundaryViolationException e) {
			e.printStackTrace();
		} 							
		return r.out;	
	}
	
	//METODI AUSILIARI; possono essere ridefiniti in sottoclassi in maniera da eseguire operazioni specifiche
	/**metodo invocato per la visita a sinistra*/
	protected void visitLeft(Position<E> v, TourResult<R> r) { }
	
	/**metodo invocato per la visita dal basso*/
	protected void visitBelow(Position<E> v, TourResult<R> r) { }
	
	/**metodo invocato per la visita a destra*/
	protected void visitRight(Position<E> v, TourResult<R> r) { }
}
I valori delle chiamate ricorsive vengono salvati nei campi di un oggetto TourResult definito come segue:
codice:
/**
 * 

Title: TourResult.java</p>
 *
 * 

Description: implementazione di un oggetto che tiene traccia dei 
 * 					risultati delle chiamate ricorsive a EulerTour.</p>
 * 					

I campi left e right tengono traccia delle chiamate 
 * 					di EulerTour sui figli destro e sinistro del nodo v 
 * 					rispettivamente, mentre out tiene traccia del valore
 * 					computato dalla chiamata di EulerTour su v.</p>
 *
 *
 */

public class TourResult<R> {
	
	public R left;
	public R right;
	public R out;
	
	/**costruttore; inizializza un oggetto TourResult vuoto*/
	public TourResult() {
		left = null;
		right = null;
		out = null;
	}

}
E di seguito ci sono le classi EvaluateExpressionTour e PrintExpressionTour che dovrebbero svolgere i calcoli:
codice:
import eccezioni.EmptyTreeException;
import eccezioni.InvalidPositionException;
import interfacce.BinaryTree;
import interfacce.Position;

/**
 * 

Title: EvaluateExpressionTour.java</p>
 *
 * 

Description: è una specializzazione di EulerTour, mediante la quale è possibile
 * 					calcolare l'espressione aritmetica salvata in un albero binario.</p>
 * 					</p>La classe "sovrascrive" il metodo ausiliario visitRight, facendogli
 * 					eseguire i seguenti calcoli:
 * 					<ul>
 * 					[*]Se v è un nodo esterno, setta <code>r.out</code> al valore della 
 * 						variabile memorizzata in v.
 * 					[*]Se v è un nodo interno, combina <code>r.left</code> e <code>r.right</code>
 * 						con l'operatore contenuto in v e setta <code>r.out</code> al risultato 
 * 						dell'operazione.
 * 					[/list]</p>
 *
 *
 */

public class EvaluateExpressionTour extends EulerTour<ExpressionTerm, Integer> {

	/**esegue l'attraversamento*/
	public Integer execute(BinaryTree<ExpressionTerm> T) {
		Integer toReturn = 0;
		
		init(T); //chiama il metodo della superclasse
		try {
			toReturn = eulerTour(tree.root()); //restituisce il valore dell'espressione
		} catch (EmptyTreeException e) {
			e.printStackTrace();
		}
		return toReturn;
	}
	
	/**esegue il calcolo dell'espressione durante la visita a destra dei nodi*/
	protected void visitRight(Position<ExpressionTerm> v, TourResult<Integer> r) {
		ExpressionTerm term = null;
		ExpressionOperator op = null;
		
		try {
			term = v.element();		
			if (tree.isInternal(v)) {
				op = (ExpressionOperator) term;
				op.setOperands(r.left, r.right);
			}
			r.out = term.getValue();
		} catch (InvalidPositionException e) {
			e.printStackTrace();
		}
	}
}
codice:
import eccezioni.EmptyTreeException;
import eccezioni.InvalidPositionException;
import interfacce.BinaryTree;
import interfacce.Position;

/**
 * 

Title: PrintExpressionTour.java</p>
 *
 * 

Description: è una specializzazione di EulerTour, mediante la quale è possibile
 * 					stampare l'espressione aritmetica salvata in un albero binario.</p>
 * 					</p>La classe "sovrascrive" i metodi ausiliari visitLeft, visitBelow 
 * 					e visitRight, facendogli eseguire le seguenti operazioni:
 * 					<ul>
 * 					[*]Durante la visita a sinistra, se v è un nodo interno stampa "(".
 * 					[*]Durante la visita dal basso stampa il valore di v.
 * 					[*]Durante la visita a destra, se v è un nodo interno stampa ")".
 * 					[/list]</p>
 *
 *
 */

public class PrintExpressionTour extends EulerTour<ExpressionTerm, String> {

	/**esegue l'attraversamento*/
	public String execute(BinaryTree<ExpressionTerm> T){
		init(T);
		System.out.print("Espressione: ");
		try {
			eulerTour(T.root());
		} catch (EmptyTreeException e) {
			e.printStackTrace();
		}
		System.out.println();
		return null; 
	}
		
	/**esegue l'attraversamento a sinistra*/
	protected void visitLeft(Position<ExpressionTerm> v, TourResult<String> r){
		try {
			if (tree.isInternal(v)) 
				System.out.print("(");
		} catch (InvalidPositionException e) {
			e.printStackTrace();
		} 	
	}
	
	/**esegue l'attraversamento a destra*/
	protected void visitBelow(Position<ExpressionTerm> v, TourResult<String> r){ 
		try {
			System.out.print(v.element());
		} catch (InvalidPositionException e) {
			e.printStackTrace();
		} 
	}
	
	/**esegue l'attraversamento dal basso*/
	protected void visitRight(Position<ExpressionTerm> v, TourResult<String> r){
		try {
			if (tree.isInternal(v)) 
				System.out.print(")");
		} catch (InvalidPositionException e) {
				e.printStackTrace();
		} 
	} 		
}
Esistono poi diverse classi ausiliarie che hanno lo scopo di fornire una rappresentazione di operatori e variabili (se necessario posso postare anche quelle).

Il problema è che durante il test la parentesizzazione dell'espressione risulta corretta, mentre operatori e variabili non vengono utilizzati come dovrebbero... vi faccio un esempio.
Data questa classe di test:
codice:
import eccezioni.InvalidPositionException;
import eccezioni.NonEmptyTreeException;
import interfacce.Position;
import tree.LinkedBinaryTree;

public class EvaluateExpressionTourTest {

	public static void main(String[] args) throws NonEmptyTreeException, InvalidPositionException {
	
		PrintExpressionTour exp = new PrintExpressionTour();
		EvaluateExpressionTour cal = new EvaluateExpressionTour();
		
		LinkedBinaryTree<ExpressionTerm> myTree = new LinkedBinaryTree<ExpressionTerm>();
		ExpressionTerm a = new AdditionOperator();
		ExpressionTerm m = new MultiplyOperator();
		ExpressionTerm f1 = new ExpressionVariable(5);
		ExpressionTerm f2 = new ExpressionVariable(10);
		ExpressionTerm f3 = new ExpressionVariable(10);
		ExpressionTerm f4 = new ExpressionVariable(2);
		
		Position<ExpressionTerm> root = myTree.addRoot(a);
		Position<ExpressionTerm> b = myTree.insertLeft(root, a);
		Position<ExpressionTerm> c = myTree.insertRight(root, m);
		myTree.insertLeft(b, f1);
		myTree.insertRight(b, f2);
		myTree.insertLeft(c, f3);
		myTree.insertRight(c, f4);
		
		exp.execute(myTree);
		System.out.println(" = " + cal.execute(myTree));
	}
il risultato che ottengo non è ((5+10)*(10+2)) ma ((5+5)+(5+5)).

Nonostante abbia passato ore sul debug non riesco a capire dov'è che le cose non funzionano e spero che qualcuno abbia la pazienza di darmi una mano. Ad ogni modo se dovessero servirvi altre informazioni ditemelo che aggiungo le altre parti del codice