Java - Problema al formar un arbol binario

 
Vista:
sin imagen de perfil
Val: 4
Ha aumentado su posición en 6 puestos en Java (en relación al último mes)
Gráfica de Java

Problema al formar un arbol binario

Publicado por Jahir (3 intervenciones) el 03/10/2018 09:53:50
Hola, buenas noches/tardes/días.
Estoy intentando hacer un árbol binario aparir de una lista doblemente enlazada, la idea es que reciba una operación como: 5*9*8= y me forme un árbol con esa cadena. No he incluido lo que debe hacer cuando ingreso los operadores de suma y resta porque este error no me deja avanzar.

Mi problema es que al llegar a la linea 50 cuando trato de asignarle un valor nulo a la hoja izquierda de la raíz de mi árbol, me cambia el valor de todas las variables a null. No logro identificar por que... si alguien puede darme una pista lo agradecería mucho. Dejo mi codigo a continuacion y la carpeta del proyecto, el error se encuentra en el codigo insertarArbol() de la clase lista.
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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
public class Nodo {
    //Variables
  private char dato;
  private boolean flag = false;
  private Nodo izq;
  private Nodo der;
  private Nodo Raiz;
 
 
  //Constructor 
  public Nodo(){}
  public Nodo(char dato){
    this.dato = dato;
  }
  //Para saber el nodo izquierdo
  public Nodo getNodoIzquierdo(){
    return izq;
  }
  //Para saber el nodo derecho
  public Nodo getNodoDerecho(){
    return der;
  }
  //Se crea nodo derecho
  public void setNodoDerecho(Nodo nodo){
    der = nodo;
  }
  //Se crea nodo Izquierdo
  public void setNodoIzquierdo(Nodo nodo){
    izq = nodo;
  }
 
  public char getDato(){
    return dato;
  }
 
  public void setDato(char dato)
  {
      this.dato = dato;
  }
 
 
    public boolean getFlag() {
        return flag;
    }
 
 
    public void setFlag(boolean flag) {
        this.flag = flag;
    }
 
    /**
     * @return the Raiz
     */
    public Nodo getRaiz() {
        return Raiz;
    }
 
    /**
     * @param Raiz the Raiz to set
     */
    public void setRaiz(Nodo Raiz) {
        this.Raiz = Raiz;
    }
 
 
 
}
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
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
public class Lista
{
    private Nodo Raiz;
    Nodo nuevo;
    Nodo arbol;
    Nodo actual;
 
    public Lista()
    {
 
    }
 
    public void insertar(char caracter)
    {
        nuevo = null;
        if(getRaiz() == null)
        {
            Raiz = new Nodo(caracter);
        }
        else if (getRaiz() != null)
        {
            nuevo = new Nodo(caracter);
            getRaiz().setNodoDerecho(nuevo);
            nuevo.setNodoIzquierdo(getRaiz());
            Raiz = nuevo;
        }
 
 
    }
    public void mostrar()
    {
        actual = Raiz;
 
        while(actual != null)
        {
            System.out.println(actual.getDato());
            actual = actual.getNodoIzquierdo();
        }
    }
    public Nodo insertarArbol()
    {
 
        actual = Raiz;
 
        while(actual != null)
        {
            if(arbol == null)
            {
                nuevo = actual;
                //El problema esta aqui abajo
                nuevo.setNodoIzquierdo(null);
                arbol = nuevo;
                actual = actual.getNodoIzquierdo();
                actual = Raiz.getNodoIzquierdo();
 
            }
            else if(actual.getDato() == '*' || actual.getDato() == '/'  )
            {
                nuevo = actual;
                nuevo.getNodoDerecho().setFlag(true);
                nuevo.getNodoIzquierdo().setFlag(false);
                nuevo.setNodoIzquierdo(actual.getNodoIzquierdo());
                nuevo.getNodoIzquierdo().setNodoIzquierdo(null);
                nuevo.getNodoIzquierdo().setNodoDerecho(null);
                nuevo.setNodoDerecho(actual.getNodoDerecho());
                nuevo.getNodoDerecho().setNodoDerecho(null);
                nuevo.getNodoDerecho().setNodoIzquierdo(null);
                nuevo.setRaiz(arbol);
                arbol = nuevo.getNodoIzquierdo();
                actual = actual.getNodoIzquierdo().getNodoIzquierdo();
                actual.setNodoDerecho(null);
 
            }
            else
            {
                actual = actual.getNodoIzquierdo();
            }
 
        }
    }
}
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
import java.util.Scanner;
 
public class ArbolBinario
{
    public static void main(String[] args)
    {
        //Declaracion de variables
        String Operacion;
        Nodo nodo;
        Lista lista = new Lista();
        Scanner sc = new Scanner(System.in);
        char caracter;
        //Ingresar operacion
        System.out.println("Ingresa una operacion");
        Operacion = sc.next();
 
        for(int i = 0 ; i < Operacion.length() ; i++)
        {
            caracter = Operacion.charAt(i);
            lista.insertar(caracter);
        }
        lista.mostrar();
        System.out.println("--------------------------------");
        lista.insertarArbol();
    }
 }
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder
Imágen de perfil de Kabuto
Val: 3.428
Oro
Ha mantenido su posición en Java (en relación al último mes)
Gráfica de Java

Problema al formar un arbol binario

Publicado por Kabuto (1381 intervenciones) el 04/10/2018 01:06:26
Hola.
Solo he podido echar un vistazo rápido por falta de tiempo, así que no estoy seguro del error, pero tengo una intuición.
En esta parte del código:
1
2
3
4
5
6
7
8
9
10
if(arbol == null)
            {
                nuevo = actual;
                //El problema esta aqui abajo
                nuevo.setNodoIzquierdo(null);
                arbol = nuevo;
                actual = actual.getNodoIzquierdo();
                actual = Raiz.getNodoIzquierdo();
 
            }

Cuando tu haces nuevo = actual, estás asignando un objeto "por referencia".
Esto significa que el objeto llamado nuevo, NO ES UNA COPIA del objeto llamado actual.
Lo que en realidad ocurre ahí es que ahora nuevo y actual son dos "nombres" que hacen referencia a un mismo objeto

Por eso, lo que le hagas a nuevo, se lo estás haciendo también a actual, y viceversa..

Y luego haces:
1
arbol = nuevo;

Ahora tienes que arbol, nuevo y actual están apuntando al mismo y único objeto.

Puedes averiguar más sobre esto si buscas info sobre la diferencia entre asignar/pasar datos por REFERENCIA o por VALOR
Pasar/Asignar por VALOR si que implica hacer una copia en un nuevo objeto, de modo que luego lo que le pase a uno, no tiene porque afectarlo al otro, porque cada uno hace referencia a su propio valor.

En lenguajes como C/C++, puedes elegir entre estas dos formas de asignar.

En Java NO, aquí todos los datos (excepto los datos primitivos como int, double, byte, char...) se asignan por REFERENCIA (con esto hay debate, en realidad, ya verás si miras por Internet..).

Para intentar evitar esto, se puede usar la sentencia new() de forma estratégica.

Por ejemplo, en esta linea:
1
nuevo.setNodoDerecho(actual.getNodoDerecho());
Ahí tendrías el mismo problema, un asignacion por REFERENCIA, no por VALOR.
Ya que setNodoDerecho() lo que hace es:
1
2
3
public void setNodoDerecho(Nodo nodo){
    der = nodo;
  }

Quizás puedas esquivar este problema si haces que el método getNodoDerecho, no haga una simple asignacion, sino que del nodo recibido, extraiga cada valor de los subnodos, inicializando previamente a der como un nuevo Nodo.
1
2
3
public void setNodoDerecho(Nodo nodo){
    der = new Nodo(nodo.getDato());
  }

Con esto, aparentemente, esquivas el problema, ya no estas referenciando al mismo nodo que recibes por parametros. Si no que estás creando un nuevo nodo totalmente original gracias a la sentencia new(), obteniendo el valor del dato del nodo recibido como argumento.

Lo único es que ahora der, tiene su dato char correcto, pero no tiene nada en sus atributos Nodo izq, Nodo der y Nodo raiz.
Por cierto, no tengo claro que todos los objetos Nodo tengan que tener un atributo Raiz, los Nodos no tienen Raiz, es el Arbol quien tiene una Raiz (que es el Nodo de donde parten el resto de Nodos)

En cualquier caso, este nuevo der al que le hemos dado un valor char tiene tres Subnodos, y cada uno de esos tres Subnodos, tiene un dato char, pero también sus propios tres Subnodos, los cuáles, también tienen su dato char y sus propios tres subnodos, lo cuáles....

Es el cuento de nunca acabar. Así que para este caso, lo de usar new() no parece una solución definitiva.

No se darte una solución, como digo, no tengo tiempo (y lo lamento) para mirar esto a fondo a ver si se me ocurre algo.


Por si a caso te sirve de algo, hace unos meses en otro foro realicé un ejercicio con un arbol binario sirviéndome de la "recursividad" para solucionarlo.

Cree una clase Nodo muy similar a la tuya, solo que sin un atributo Raiz.
Cree luego una clase Arbol, quen si tiene un atributo Raiz, que es en realidad un Nodo, quien contrendrá subnodos, quienes a su vez tendrán más subnodos, etc...

Y otra clase Test para ponerlo a prueba, donde se le pasan al Arbol una serie de valores y se van ramificando creando subnodos a un lado u a otro según su valor, de forma recursiva...
Es un planteamiento más simple que el de tu ejercicio.
Echale un vistazo, por si te puede servir de ayuda
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar
sin imagen de perfil
Val: 4
Ha aumentado su posición en 6 puestos en Java (en relación al último mes)
Gráfica de Java

Problema al formar un arbol binario

Publicado por Jahir (3 intervenciones) el 04/10/2018 02:47:39
Muchas gracias por responderme, realmente me has ayudado aclarándome lo de pasar/asignar datos por referencia o valor, no tenia conocimiento de eso. Voy a darme una vuelta al ejercicio que mencionas. Continuo buscando alguna solución, pero ahora ya se al menos cual es el problema jaja.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar