3
Hello, everyone. I started studying the Java language recently and decided to try to create a binary tree with three features:
1 - Add element to tree
2 - Search and print tree widget
3 - Remove tree element (relocating your children)
The third feature should be made so that, for example, a binary tree that has root value 3 and children 2 and 5, upon receiving the command to remove value 3, should keep values 2 and 5 in the tree. That is, when removing the parent knot, your children are not removed, but reinserted into the tree.
With that in mind, I created the Tree class that follows below:
package org.hello;
import javax.swing.JOptionPane;
public class Arvore {
int valor;
Arvore left = null;
Arvore right = null;
String e,d;
int size;
Arvore(){
size=0;
}
Arvore(int x){
valor=x;
size=0;
}
int insert(Arvore root,int valor){
Arvore a = new Arvore(valor);
if(root == null){
root = a;
root.size++;
JOptionPane.showMessageDialog(null, "Elemento Adicionado!.");
}
else{
if(valor > root.valor){
if(root.right == null){
root.right = a;
root.size++;
a.size = root.size;
JOptionPane.showMessageDialog(null, "Elemento Adicionado!.");
}
else{
return insert(root.right,valor);
}
}
else {
if(valor < root.valor){
if(root.left == null){
root.left = a;
root.size++;
a.size = root.size;
JOptionPane.showMessageDialog(null, "Elemento Adicionado!.");
}
else{
return insert(root.left,valor);
}
}
else{
if(valor == root.valor){
JOptionPane.showMessageDialog(null, "Elemento já existente.");
}
}
}
}
return 0;
}
int buscar(Arvore root, int valor){
if(root == null){
JOptionPane.showMessageDialog(null, "Elemento não encontrado.");
}
else{
if(root.valor == valor){
if(root.left == null ){
root.e = "vazio" ;
}
else{
root.e = Integer.toString(root.left.valor);
}
if(root.right == null){
root.d = "vazio";
}
else{
root.d = Integer.toString(root.right.valor);
}
JOptionPane.showMessageDialog(null,"Valor: "+root.valor+"\n"+"Esquerdo: "+root.e+"\n"+"Direito: "+root.d+"\n\n");
}
else{
if(root.valor < valor){
return buscar(root.right,valor);
}
else{
return buscar(root.left,valor);
}
}
}
return 0;
}
Arvore novo_no(Arvore source,Arvore dest){
if(source.right==null && source.left==null){
return dest;
}
else{
if(source.right != null && source.left != null){
dest.insert(dest,source.left.valor);
dest.insert(dest,source.right.valor);
dest = novo_no(source.left,dest);
dest = novo_no(source.right,dest);
return dest;
}
else{
if(source.right != null && source.left == null){
dest.insert(dest,source.right.valor);
dest = novo_no(source.right,dest);
return dest;
}
else{
dest.insert(dest,source.left.valor);
dest = novo_no(source.left,dest);
return dest;
}
}
}
}
int remove(Arvore root, int valor){
if(root==null){
JOptionPane.showMessageDialog(null,"Elemento não cadastrado.");
}
else{
if(root.valor == valor){
Arvore dest = new Arvore();
dest = null;
root = novo_no(root,dest);
return 0;
}
else{
if(root.valor > valor){
return remove(root.left,valor);
}
else{
return remove(root.right,valor);
}
}
}
return 0;
}
}
The functions 'Insert' and 'fetch', responsible for inserting and fetching the elements in the tree, respectively, are working normally. Already the 'remove' and 'new_no' functions, which act together to remove an element from the tree, do not work well, generating the error mentioned in the title.
OBS: I’m not sure if the two functions have errors or if only one of them is wrong. So I’d like your help to understand why the program doesn’t work the way you want it to.
On the behaviour of the programme:
By adding the numbers 5,6 and 4 to the tree as a test, and searching for any of them, the program works perfectly. However, when trying to remove any of the child nodes(4 and 6), the program acts as if it has removed them, when it is actually still possible to pick them up from the tree. When attempting to remove the parent node(5), the program terminates and displays the error lines below:
Exception in thread "main" java.lang.NullPointerException
at org.hello.Arvore.novo_no(Arvore.java:100)
at org.hello.Arvore.remove(Arvore.java:128)
at org.hello.Principal.main(Principal.java:40)
at org.hello.Principal.main(Principal.java:36)
at org.hello.Principal.main(Principal.java:41)
at org.hello.Principal.main(Principal.java:36)
at org.hello.Principal.main(Principal.java:26)
at org.hello.Principal.main(Principal.java:26)
at org.hello.Principal.main(Principal.java:22)
I checked the lines mentioned above, but could not understand what was wrong. So I count on your help to understand what happened. Below is the main function:
package org.hello;
import java.util.Scanner;
import javax.swing.JOptionPane;
public class Principal {
static Arvore pai = null;
public static void main(String[] args){
int escolha = Integer.parseInt(JOptionPane.showInputDialog("Escolha uma opção: \n\n 1-Adicionar elemento \n 2-Buscar elemento \n 3-Remover elemento \n"));
switch(escolha){
case 1:
int valor = Integer.parseInt(JOptionPane.showInputDialog("Digite o valor a ser adicionado: "));
if(pai==null){
Arvore a = new Arvore(valor);
pai = a;
JOptionPane.showMessageDialog(null, "Elemento Adicionado!.");
pai.size++;
main(null);
break;
}
pai.insert(pai, valor);
main(null);
break;
case 2:
int valor2 = Integer.parseInt(JOptionPane.showInputDialog("Digite o valor a ser buscado: "));
if(pai == null){
JOptionPane.showMessageDialog(null,"Elemento não existente.");
main(null);
break;
}
pai.buscar(pai, valor2);
main(null);
break;
case 3:
int valor3 = Integer.parseInt(JOptionPane.showInputDialog("Digite o valor a ser removido: "));
pai.remove(pai, valor3);
main(null);
break;
}
}
}
Thank you in advance!
Hello again. According to @cleberz, the following block was not working by providing a null value for the function novo_no
:
...
if(root.valor == valor){
Arvore dest = new Arvore();
dest = null; //pra quê anular se você
//acabou de inicializar?
root = novo_no(root,dest); //isso manda um nulo aqui
return 0;
}
...
After the correction, this block was like this:
...
if(root.valor == valor){
Arvore dest = new Arvore();
root = novo_no(root,dest);
/* 1 */
return 0;
}
...
However, on the line /* 1 */
, if I put 3 JOptionPane.showMessageDialog()
to show the value of the new node(root) and the value of your 2 children, I have the following return:
node value: 0
value right node: 4
value left node: null
That’s when we just add the numbers 5, 4 and 6 to the tree. But although this is not the desired return, since the value of the node should be the number 4, while the number 6 would be his right child, when fetching the value 5 in the tree again he is still there, even if the value of root
should have been changed before the function remove
return. I wonder why the root value does not change, in this case.
Removing the line
dest = null
, the program does not give more error, but still it does not modify the node that should be removed. Using the above example, insert the numbers 5,4 and 6 into the tree,root
receives a node of value 0 and children 4 and null as function returnnovo_no
, which is not the desired result. But still, the root value is not modified. What could that be?– João Luca