I have a problem comparing nodes (of binary tree) to null
Say node is a new root of the tree, with key=5.
In the constructor I set node's left, right and parent to be null
(fields: private Node left=null,right=null,parent=null;
constructor: this.key=key)
When I print the node's left child (same as for the right and the parent) I get null as expected.
However, node.left==null (or node.getLeft()==null) gets me false. why?
Here's the code of node class:
public class Node{
private Node parent = null, left = null, right = null;
private int key;
public Node(int key) {
this.key = key;
}
public Node getParent() {
return parent;
}
public Node getLeft() {
return left;
}
public Node getRight() {
return right;
}
public void setParent(Node parent) {
this.parent = parent;
}
public void setLeft(Node child) {
this.left = child;
}
public void setRight(Node child) {
this.right = child;
}
public void setKey(int key) {
this.key = key;
}
}
Related
I have a binarySearch Tree and I want to create a method assignFirst.
This method should find the node in the tree with the smallest value and
update the tree's "first" attribute accordingly.
I have a lot of methods, but I don't want to include all of them in here, since I want to keep it short and simple.
Therefore, I will include the class and some features inside that class.
public class BinarySearchTree<E extends Comparable<E>>
{
private BSTNode<E> root; // root of overall tree
private int numElements;
private BSTNode<E> first;
// post: constructs an empty search tree
public BinarySearchTree()
{
this.root = null;
this.numElements = 0;
}
private void assignFirst()
{
if (root.left == null)
{
first.data = root.data;
}
else
{
first.data = root.left.data;
}
}
public class Iterator
{
private BSTNode<E> currentNode;
public Iterator()
{
currentNode = first;
}
public boolean hasNext()
{
return currentNode != null;
}
public E next()
{
E value = currentNode.data;
currentNode = currentNode.next;
return value;
}
}
private static class BSTNode<E>
{
public E data;
public BSTNode<E> left;
public BSTNode<E> right;
public BSTNode<E> parent;
public BSTNode<E> next;
public BSTNode(E data)
{
this(data, null, null, null, null);
}
public BSTNode(E data, BSTNode<E> left, BSTNode<E> right, BSTNode<E> parent, BSTNode<E> next)
{
this.data = data;
this.left = left;
this.right = right;
this.parent = parent;
this.next = next;
}
}
}
I updated my method look like this. I'm still uncertain if this is the correct way of doing it.
private void assignFirst()
{
if (first.left != null)
{
first = first.left;
}
else
{
first = root;
}
}
I figured it out. I wrote it in like this.
private void assignFirst()
{
BSTNode<E> node = root;
while(node.left != null)
{
node = node.left;
}
first = node;
}
I am using the following code to convert a flat structure like:
test/test2/test3
test/test5/test2
test/test7/test5/test4
test/test7/test5/test9
into a tree like:
test
| | |
test2 test5 test7
| | |
test3 test2 test5
| |
test4 test9
The code:
import java.util.*;
class Tree
{
class Node
{
String data;
ArrayList<Node> children;
public Node(String data)
{
this.data = data;
children = new ArrayList<Node>();
}
public ArrayList<Node> getChildren()
{
return children;
}
public Node getChild(String data)
{
for(Node n : children)
if(n.data.equals(data))
return n;
return null;
}
}
private Node root;
public Tree()
{
root = new Node("");
}
public boolean isEmpty()
{
return root==null;
}
public void add(String str)
{
Node current = root;
StringTokenizer s = new StringTokenizer(str, "/");
while(s.hasMoreElements())
{
str = (String)s.nextElement();
Node child = current.getChild(str);
if(child==null)
{
current.children.add(new Node(str));
child = current.getChild(str);
}
current = child;
}
}
public void get()
{
return root;
}
}
I use the "add" function to split the above flat paths to a tree and it works nicely and I am able to navigate forward. Though, I want to be able to navigate to the Node with a given path and also when I navigate to some Node, I want to be able to trace it to the root element. For example, if I navigate from test -> test2 -> test3, I want to get the path from the root like test/test2/test3.
I am new to Trees and the topic is confusing me a bit, your help is highly appreciated.
Edit: Added a visual representation.
public class Tree {
private final Node root = new Node(null, null);
public boolean isEmpty() {
return root.children.isEmpty();
}
public void add(String path) {
Node parent = root;
for (String data : path.split("/")) {
Node node = parent.getChild(data);
if (node == null)
parent.children.add(node = new Node(data, parent));
parent = node;
}
}
public Node get(String path) {
Node parent = root;
for (String data : path.split("/")) {
Node node = parent.getChild(data);
if (node == null)
return null;
parent = node;
}
return parent;
}
public static final class Node {
private final String data;
private final Node parent;
private final List<Node> children = new LinkedList<>();
public Node(String data, Node parent) {
this.data = data;
this.parent = parent;
}
public List<Node> getChildren() {
return Collections.unmodifiableList(children);
}
public Node getChild(String data) {
for (Node node : children)
if (node.data.equals(data))
return node;
return null;
}
public String getPath() {
Deque<String> nodes = new LinkedList<>();
Node node = this;
while (node.parent != null) {
nodes.addFirst(node.data);
node = node.parent;
}
return String.join("/", nodes);
}
#Override
public String toString() {
return data;
}
}
public static void main(String... args) {
Tree tree = new Tree();
tree.add("test/test2/test3");
tree.add("test/test5/test2");
tree.add("test/test7/test5/test4");
tree.add("test/test7/test5/test9");
Node node = tree.get("test/test7/test5/test9");
String path = node.getPath();
}
}
A simple way is to keep track of the parent node, then just follow the parents up the tree from the child:
Node currentNode = ...
ArrayList<Node> path = new ArrayList<>();
while(currentNode != null){
path.add(currentNode);
currentNode = currentNode.getParent();
}
Collections.reverse(path);
So your Node class would need a new constructor:
class Node {
String data;
ArrayList<Node> children;
Node parent;
Node(Node parent, String data){
// ...
}
// ...
// Null if this is the root, else returns the parent node
public Node getParent(){ return parent; }
}
I have constructed a Tree class as shown below:
public class Node {
private int label;
private ArrayList<Node> children;
private Node parent;
public Node(int label) {
this.label = label;
this.children = new ArrayList<Node>();
this.parent = null;
}
public void addChild(Node child) {
this.children.add(child);
}
public int getLabel() {
return this.label;
}
public ArrayList<Node> getChildren() {
return this.children;
}
public Node getParent() {
return this.parent;
}
public void setParent(Node parent) {
this.parent = parent;
}
}
Assuming that I have a non binary Tree:
1
|
9
/ | \
3 0 7
How can I write a method in order to get the level of a leaf (say node labelled with 7) in a non-binary Tree?
public int getLevel() {
if (parent == null) return 0;
// Additional code is needed here
}
The level is often called the depth or height.
public int getLevel(){
Node temp = parent;
int depth = 0;
while(temp != null){
depth++;
temp = temp.parent;
}
return depth;
}
This will not work if there is a cycle of course, but there shouldn't be one in a tree anyways.
I am extremely new to java, and all my other searches lead to something more complex than my given question so I was wondering how i may go about this? i would like for my tree nodes to have consist of the following fields: parent, left, right and data.
Since you're new to Java the most basic structure would be like this:
public class Node {
private Node parent, left, right;
private Integer data;
public Node(Node parent, Node left, Node right, Integer data) {
this.parent = parent;
this.left = left;
this.right = right;
this.data = data;
}
public Node getParent() { return this.parent; }
public Node getLeft() { return this.left; }
public Node getRight() { return this.right; }
public Integer getData() { return this.data; }
public void setParent(Node parent) { this.parent = parent; }
public void setLeft(Node left) { this.left = left; }
public void setRight(Node right) { this.right = right; }
public void setData(Integer data) { this.data = data; }
}
If you want to take it one step further and learn more about Object-Oriented Programming I would look into generics.
public class Node<T extends Comparable<T>> {
private Node parent, left, right;
private T data;
// Getters, setters, compare methods here
}
This will let you declare a Node<Integer>, Node<String>, Node<CustomClass> to let you not be restricted to a certain type of data. You'll want to do extend Comparable<T> so that you can easily compare objects when doing an insert(), and other Tree functions.
I'm trying to build an raw type BST, with Comparable<T>. The thing is somehow my declarations do something wrong, because I use in Node class type Comparable<type> and in BST class it errors with
The method setParent(Node<Comparable<Comparable<type>>>) in the type
Node<Comparable<type>> is not applicable for the arguments (Node<Comparable<type>>)
BinarySearchTree.java /lab2/src line 22 Java Problem
Node.java:
public class Node <type> {
private Comparable<type> key;
private Node <Comparable<type>> parent;
private Node <Comparable<type>> leftChild;
private Node <Comparable<type>> rightChild;
public Node(Comparable<type> key, Node <Comparable<type>> leftChild, Node <Comparable<type>> rightChild) {
this.setKey(key);
this.setLeftChild(leftChild);
this.setRightChild(rightChild);
}
public void setKey(Comparable<type> key) {
this.key = key;
}
public Comparable<type> getKey() {
return key;
}
public void setParent(Node<Comparable<type>> y) {
this.parent = y;
}
public Node <Comparable<type>> getParent() {
return parent;
}
public void setLeftChild(Node <Comparable<type>> leftChild) {
this.leftChild = leftChild;
}
public Node <Comparable<type>> getLeftChild() {
return leftChild;
}
public void setRightChild(Node <Comparable<type>> rightChild) {
this.rightChild = rightChild;
}
public Node <Comparable<type>> getRightChild() {
return rightChild;
}
}
BinarySearchTree.java:
import java.util.Iterator;
public class BinarySearchTree<type> implements SortedSet<type> {
private Node <Comparable<type>> root;
public void insert(Node <Comparable<type>> z) {
Node <Comparable<type>> y = null;
Node <Comparable<type>> x = root;
while (x != null) {
y = x;
if (z.getKey() < x.getKey()) { // ERROR '<' is undefined for type...
x = x.getLeftChild(); // PARAM TYPE ERROR
} else {
x = x.getRightChild(); // PARAM TYPE ERROR
}
}
z.setParent(y);
if (y == null) {
root = z;
} else if (z.getKey() < y.getKey()) {
y.setLeftChild(z);
} else {
y.setRightChild(z);
}
}
Consider to refactoring to the following code
import java.util.SortedSet;
public abstract class BinarySearchTree<T extends Comparable<T>> implements SortedSet<T> {
private Node<T> root;
class Node<T extends Comparable<T>> {
private T key;
private Node<T> parent;
private Node<T> leftChild;
private Node<T> rightChild;
public Node(T key, Node<T> leftChild, Node<T> rightChild) {
this.setKey(key);
this.setLeftChild(leftChild);
this.setRightChild(rightChild);
}
public void setKey(T key) {
this.key = key;
}
public T getKey() {
return key;
}
public void setParent(Node<T> y) {
this.parent = y;
}
public Node <T> getParent() {
return parent;
}
public void setLeftChild(Node <T> leftChild) {
this.leftChild = leftChild;
}
public Node <T> getLeftChild() {
return leftChild;
}
public void setRightChild(Node <T> rightChild) {
this.rightChild = rightChild;
}
public Node <T> getRightChild() {
return rightChild;
}
}
public void insert(Node<T> z) {
Node<T> y = null;
Node<T> x = root;
while (x != null) {
y = x;
if (z.getKey().compareTo(x.getKey()) < 0) {
x = x.getLeftChild();
} else {
x = x.getRightChild();
}
}
z.setParent(y);
if (y == null) {
root = z;
} else if (z.getKey().compareTo((T) y.getKey()) <0) {
y.setLeftChild(z);
} else {
y.setRightChild(z);
}
}
}