I have created a binary search tree in java that allow user to add nodes to the tree
This is my implementation of the binary tree in java which accept root node on creation and then automatically figure out that it should add the child into left side or right side of the tree.
public class BinarySearchTree {
Node root = null;
public BinarySearchTree(Node root){
this.root =root;
}
public void add(int data){
Node newNode = new Node(data);
if(this.root ==null){
newNode =this.root;
}
if(data>this.root.data){
addRight(root,newNode);
}
if(data<this.root.data){
addLeft(root,newNode);
}
}
public Node getRoot(){
return this.root;
}
private void addLeft(Node root, Node newNode) {
if(root.leftChild == null){
root.leftChild = newNode;
}
else {
this.root = this.root.leftChild;
add(newNode.data);
}
}
private void addRight(Node root,Node newNode) {
if (root.rightChild == null){
root.rightChild = newNode;
}
else {
this.root = this.root.rightChild;
add(newNode.data);
}
}
}
But when I try to retrieve the root node with getRoot() method. it return me the child of the root rather than the actual root node that I had passed in.
this is a example of using it
TreeHight treeHight = new TreeHight();
Node root = new Node(100);
BinarySearchTree unbalance = new BinarySearchTree(root);
unbalance.add(200);
unbalance.add(50);
unbalance.add(250);
unbalance.add(350);
when I try to get root node it give me 250 as the first node rather than 100.
How can I retrieve the root node of this tree ?
In your code you write:
this.root = this.root.leftChild;
add(newNode.data);
This is probably wrong behavior?
You should rewrite it to:
add(this.root.leftChild,newNode);
And then define a recursive method that looks whether the item should be stored left/right of the subroot.
Something like:
public void add(Node subroot, int data){
if(data > subroot.data){
addRight(subroot,data);
}
else if(data < subroot.data){
addLeft(subroot,newNode);
}
}
private void addLeft(Node subroot, int data) {
if(subroot.leftChild == null){
subroot.leftChild = new Node(data);
}
else {
add(subroot.leftChild,data);
}
}
private void addRight(Node subroot, int data) {
if(subroot.rightChild == null){
subroot.rightChild = new Node(data);
}
else {
add(subroot.rightChild,data);
}
}
And the add method is then:
public void add(int data){
if(this.root == null){
this.root = new Node(data);
}
else {
this.add(this.root,data);
}
}
I think an invariant of a binary tree is that the root remains the same. The same goes for addRight by the way.
Finally you also wrote:
newNode =this.root;
in your add method, this of course, doesn't make much sense.
You are editing the root in this line:
this.root = this.root.rightChild;
I think you should add the new node to the right recursively like this:
else {
addRight(this.root.rightChild, newNode);
}
And just as a note i think you have problem in this block "in the add method":
if(this.root ==null){
newNode =this.root; // it should be this.root = newNode;
}
Related
When I create a Node object and call "appendToTail" the Node object has a sequence of nodes via the next attribute (as expected). I tried creating a pop, where it takes the head (aka 'this') and reference it with a variable and overwrite it with its next. However, 'this' remains the same as the original head. What am I doing wrong, or is there no way to modify 'this'?
public class Node {
Node next = null;
int data;
public Node(int d) {
data = d;
}
public void appendToTail(int d) {
Node end = new Node(d);
Node n = this;
while (n.next != null) {
n = n.next;
}
n.next = end;
}
public void popHead() {
Node n = this;
n = n.next;
}
}
Basically you need to construct a custom List and add each node at End. Also you need to store first node in order to have the starting point for looping.
public class NodeList
{
Node head=null;
public static void main(String args[])
{
NodeList nl = new NodeList();
nl.addNode(1);
nl.addNode(2);
nl.addNode(3);
nl.listNodes();
}
public void addNode(int data)
{
if(head==null)
{
head = new Node(data);
}
else
{
Node curent = head;
while(curent.next != null)
{
curent = curent.next;
}
curent.next = new Node(data);
}
}
public void listNodes()
{
if(head !=null)
{
Node curent = head;
System.out.println(curent.data);
while(curent.next !=null)
{
curent = curent.next;
System.out.println(curent.data);
}
}
}
class Node
{
Node next = null;
int data;
public Node(int d) {
data = d;
}
}
}
Output
1
2
3
I am having trouble with my add method, I believe that the error occurs in the parameters passed in the public method, however I'm not sure if my private helper method is also not adding the correct variables.
Here are the instructions to my addMethod
The add(E) method may additionally call the assignFirst() method to assign the first attribute in case it should be changed. The add helper method should now assign each node's "parent" and "next" references when a new node is created.
• The "parent" parameter should reference a newly created node's parent node, so when
creating a new node, you can simply assign its parent to this parameter.
• The "prev" parameter should reference a newly created node's previous node, so when
creating a new node, you can simply update the "next" references in the appropriate
nodes. The tricky part is knowing what values to pass when you're calling the add
helper method. Here's the logic:
• If the add helper return value is to be a right child, then that right child's previous
node should be the same as its parent. The optional getPrevNode won't be helpful
here since the previous node will be the new node's parent, and the new node isn't
yet attached to the tree.
• If the add helper return value is to be a left child, then that left child's previous node
could be determined by the optional getPrevNode method, asking it for the node that
is before the current node parameter.
Here is my code:
public void add(E value)
{
this.root = add(root, value, root, null);
assignFirst();
}
// post: value added to tree so as to preserve binary search tree
private BSTNode<E> add(BSTNode<E> node, E value, BSTNode<E> parent, BSTNode<E> prev)
{
if (node == null)
{
node = new BSTNode<E>(value);
node.parent = parent;
node.next = prev;
this.numElements++;
}
else if (node.data.compareTo(value) > 0)
{
node.left = add(node.left, value, node , getPrevNode(node));
}
else if (node.data.compareTo(value) < 0)
{
node.right = add(node.right, value, node, node.parent);
}
return node;
}
private void assignFirst()
{
BSTNode<E> node = root;
while(node.left != null)
{
node = node.left;
}
first = node;
}
private BSTNode<E> getPrevNode(BSTNode<E> node)
{
if(node.left != null)
{
node = node.left;
while(node.right != null)
{
node = node.right;
}
return node;
}
else if(node.parent != null)
{
if(node.parent.right == node)
{
return node.parent;
}
if(node.parent.left == node)
{
while(node.parent != null && node.parent.left == node)
{
node = node.parent;
}
if(node == root)
{
return null;
}
else
{
return node.parent;
}
}
}
return null;
}
Here is some background information, however I'm leaving some methods out since they're irrelevant to what I am trying to figure out. Therefore I am cutting it short.
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;
}
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;
}
}
}
This was a rigorous process, here's what I got
public void add(E value)
{
this.root = add(root, value, root, null);
assignFirst();
}
// post: value added to tree so as to preserve binary search tree
private BSTNode<E> add(BSTNode<E> node, E value, BSTNode<E> parent, BSTNode<E> prev)
{
if (node == null)
{
node = new BSTNode<E>(value);
node.parent = parent;
if(prev == null)
{
node.next = parent;
}
else
{
node.next = prev.next;
prev.next = node;
}
this.numElements++;
}
else if (node.data.compareTo(value) > 0)
{
node.left = add(node.left, value, node , getPrevNode(node));
}
else if (node.data.compareTo(value) < 0)
{
node.right = add(node.right, value, node, node);
}
return node;
}
The method not working:
public void insert_before_node(Node givenNode, int data) {
Node newNode = new Node(data);
newNode.prev = givenNode.prev;
givenNode.prev = newNode;
newNode.next = givenNode;
if(newNode.prev != null)
newNode.prev.next = newNode;
}
Another add method which is working:
public void insert_front(int data) {
Node newNode = new Node(data);
newNode.next = head;
newNode.prev = null;
if(head != null)
head.prev = newNode;
head = newNode;
}
A print method to debug:
public void print() {
Node n = head;
while(n != null){
System.out.println(n.data);
n = n.next;
}
}
DoublyLinkedList class:
public class DoublyLinkedList {
static class Node {
int data;
Node next;
Node prev;
Node(int data) {
this.data = data;
this.next = null;
this.prev = null;
}
}
Node head;
DoublyLinkedList() {
this.head = null;
}
public static void main(String[] args) {
DoublyLinkedList ll = new DoublyLinkedList();
ll.insert_front(0);
ll.insert_before_node(ll.head, 100);
ll.print();
}
}
LinkedList and Node implementations are very straightforward. Find here: https://www.geeksforgeeks.org/doubly-linked-list/
I first create a linkedlist, insert_front() a value to make the head not null, then use the method above to insert something else. Insertion to front, end, after a node are working, however, this insert_before_node() is not working. What I have inserted with this method is not appears on my print.
I draw on a paper too, still couldn't find the problem.
The geeksforgeeks link also has no java implementation for this method.
Your code is working, apart from the assignment of head in insert_front(Node,int) method, I think you forgot this. before that.
Plus, maybe you would need to
remove the head argument in insert_front method (it's the head of the dll, it has a class member for that),
remove the underscores (not Java good practice, Sonar would complain)
return the nodes you create so you can later reference them (and possibly create a fluent API)
A basic rework would look like this MVP:
import java.util.Objects;
public class DoubleLinkLists {
public static void main(String[] args) {
DoubleLinkedList dll = new DoubleLinkedList();
DoubleLinkedList.Node node5 = dll.insertInFront(5);
DoubleLinkedList.Node node4 = dll.insertInFront(4);
DoubleLinkedList.Node node2 = dll.insertInFront(2);
DoubleLinkedList.Node node1 = dll.insertInFront(1);
DoubleLinkedList.Node node3 = dll.insertBefore(node4, 3);
System.out.println(dll);
}
public static class DoubleLinkedList {
Node head;
#Override
public String toString() {
Node current = head;
StringBuilder sb = new StringBuilder();
while (current != null) {
sb.append(current.data)
.append(" ");
current = current.next;
}
return sb.toString();
}
public Node insertBefore(Node givenNode, int data) {
Node newNode = new Node(data);
newNode.prev = givenNode.prev;
givenNode.prev = newNode;
newNode.next = givenNode;
if (newNode.prev != null) {
newNode.prev.next = newNode;
}
return newNode;
}
public Node insertInFront(int data) {
Node newNode = new Node(data);
newNode.next = head;
newNode.prev = null;
if (head != null) {
head.prev = newNode;
}
head = newNode;
return newNode;
}
public static class Node {
int data;
Node prev;
Node next;
Node(int d) {
data = d;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Node node = (Node) o;
return data == node.data;
}
#Override
public int hashCode() {
return Objects.hash(data);
}
}
}
}
I edit the code for more readable.
public void insert_before_node(Node next, int data) {
Node newNode = new Node(data);
Node prev = next.prev;
//left to right
prev.next = newNode;
newNode.next = next;
//traverse right to left
next.prev = newNode;
newNode.prev = prev;
}
I assume the next and prev is also not null.
By the way, you should add more condition to detect null(next and prev) in insert_before_node.
Please update the result and hope it help.
I have a BinaryTree class which contains an inner class Node.
What I would like to do is to be able to insert some nodes in my BinaryTree tree by calling tree.insert(node). However, to keep it clean and consistent, I dont want to create an insert() method inside Node inner class. So I tried the code below, but I have an error: Cannot cast from BinaryTree.Node to BinaryTree.
What should I do?
BinaryTree class
public class BinaryTree {
Node root = null;
private class Node {
int value;
Node left;
Node right;
}
public BinaryTree(int v) {
root.value = v;
root.left = null;
root.right = null;
}
public void insert(Node n) {
/* Error */
if(n.value > root.value) ((BinaryTree) root.right).insert(n);
}
}
Main class
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
String[] str = sc.nextLine().split(" ");
BinaryTree tree;
for(int i = 0; i < str.length-1; i++) {
int val = Integer.parseInt(str[i]);
//tree.insert(node);
}
}
}
Thanks,
You don't need typecasting inside insert method. It should be like this:
public void insert(Node n) {
if(n.value > root.value)
insert(root.right);
}
To insert a node in a tree you need to define where to insert it, so your insert methods should be something like:
//insert a new node right to a node. not null safe
public void insert(Node newNode, Node rightTo) {
newNode.right = rightTo.right;
newNode.left = rightTo;
rightTo.right = newNode;
}
which does not require casting.
To find the rightTo node you could use:
//get the last node which has a value lower than `value`
//may return null
public Node getNodeWithValueLowerThan(int value) {
if(root == null) return null;
return getNodeWithValueLowerThan(root, value);
}
//recursive method. null safe
private Node getNodeWithValueLowerThan(Node node, int value) {
if(node == null) return null;
if(node.value > value) return node.left; //return previous node. may be null
return getNodeWithValueLowerThan(node.right, value);
}
To insert a node as a last node, you could use:
//insert a new node as last
public void insertLastNode(Node newNode) {
Node lastNode = getTail();
if(lastNode == null) {//empty tree
root = newNode;
return;
}
newNode.left = lastNode;
lastNode.right = newNode;
}
where getTail is something like:
//find last node
private Node getTail() {
if(root == null) return null;
return getTail(root);
}
//recursive method to find last node. not null safe
private Node getTail(Node node) {
if(node.right == null) return node;
return getTail(node.right);
}
Note: code was not tested so debug carefully.
I am trying to implement linked list in java, but nothing gets printed out. I tried debugging it and it seems that every time the Add function gets called the previous value gets over written. However when i check the logic of it, it should work.
public class MyLinkedList {
public Node head;
public Node curr;
public MyLinkedList() {
// TODO Auto-generated constructor stub
head = null;
curr = null;
}
public void Add(int data) {
Node box = new Node();
box.data = data;
box.next = null;
curr = head;
if (curr == null) {
head = box;
curr = null;
}
else {
while (curr.next != null) {
curr = curr.next;
}
curr.next = box;
}
}
public void Print() {
curr = head;
while (curr != null) {
System.out.println(curr.data);
curr = curr.next;
}
}
}
This is what the Node class has
public class Node {
public int data;
public Node next;
}
Your code is fine. Just go and delete *.class files. It may be stuck in early stages of your code.
*.class files located under output folder (name of the folder can change depending on the IDE you used but generally under build folder.) you may need to delete that folder completely.
It works already, but I'll tidy it up for you:
public class MyLinkedList {
private Node head; //never expose a field as public
//the whole constructor was unnecessary
public void add(int data) { //methods start with a lower case
add(new Node(data)); //nodes always need data, so I'm passing in constructor
}
// this method adds an existing node rather than the previous add both
// creating, finding the end and adding
private void add(Node node) {
if (head == null) {
head = node;
} else {
lastNode().next = node;
}
}
private Node lastNode() { //finds the last node in the chain
Node curr = head; //curr is local
while (curr.next != null) {
curr = curr.next;
}
return curr;
}
public void print() { //methods start with a lower case
Node curr = head; //curr is local
while (curr != null) {
System.out.println(curr.data);
curr = curr.next;
}
}
private static class Node { //this class is just useful internally to MyLinkedList
private final int data; //final - node data doesn't change
private Node next;
private Node(int data) {
this.data = data;
}
}
}