I am creating a tree and learning TDD. I am not sure how I can detect the root here while adding node. Essentially I want 1 -> 2 -> 3 formed. I think thats how it would look in memory with my current setup. Obviously below test fails. (partly)
Test code:
#Test
public void test() {
Nodes root = new Nodes(4);
assertNotNull(root);
root.addNode(5);
root.addNode(6);
assertEquals(5, root.printNodes(root)[1]);
assertEquals(6, root.printNodes(root)[2]);
}
When I am adding a node, I want to add it to the root.
public class Nodes {
int data;
Nodes next;
Nodes(int data) {
this.data = data;
}
public void addNode(int i) {
Nodes newNode = new Nodes(i);
while (newNode.next != null) {
//detect root and add the newnode
}
}
public int[] printNodes(Nodes root) {
int[] n = new int[5];
int i = 0;
while (root != null) {
n[i] = root.data;
root = root.next;
i++;
}
return n;
}
}
root.addNode(5);
root.addNode(6);
With your current code, you don't need to detect what the root node is (you already have it with root), you need, instead, to detect the order of inserted nodes.
So your addNode could be something like the following:
public void addNode(int i)
{
if (i == this.data) {
// what do you do when data equal?
} else {
if (this.next != null) {
if (this.next.data < i) {
this.next.next = new Nodes(i);
} else {
Nodes tmp = new Nodes(i);
tmp.next = this.next;
this.next = tmp;
}
} else {
this.next = new Nodes(i);
}
}
}
And then your printNodes function:
public void printNodes()
{
Nodes tmp = this;
while (tmp != null) {
System.out.printf("%d\n", tmp.data);
tmp = tmp.next;
}
}
This implementation is, of course, not a binary tree, but you've stated you are wanting to start with this implementation and expand from there, so I hope this can help you get there.
Related
I have troubles with traversing through a array binary tree without recursion.
I hope someone can tell me what iam doing wrong. For simplicity the code is kept simple.
Please note: Its not allowed to add other methods like Iterator to check if there is a hasNext() and so on.
For now i just want to print all keys out (incl. child keys) in the hope that i can do the rest of the learning!
Thank you very much for helping.
public class BTree {
private Node root;
public BTree(Node root) {
this.root = root;
}
public int getMaxKey() {
Node copy = root;
for (int i = 0; copy.child != null && i < copy.child.length; i++) {
System.out.println("key: " + copy.key); // output: 15, 80
if (copy.child != null) {
copy = copy.child[i];
}
}
return 0;
}
}
public class Node {
public int key;
public Node[] child;
public Node(int key, Node[] child) {
this.key = key;
this.child = child;
}
}
public class NodeMain {
public static void main(String[] args) {
Node[] lv1Nodes = new Node[2];
lv1Nodes[0] = new Node(25, null);
lv1Nodes[1] = new Node(99, null);
Node[] lv0Nodes = new Node[2];
lv0Nodes[0] = new Node(80, lv1Nodes);
lv0Nodes[1] = new Node(5, null);
Node root = new Node(15, lv0Nodes);
BTree bTree = new BTree(root);
int maxKey = bTree.getMaxKey(); // output should be 99
System.out.println(maxKey);
}
}
So, here you are following only one branch till null for the Binary tree traversal. But, you need to keep track of all nodes in traversal order of child array so that you can get the max element from it.
please refer to below code, here i've used stack to keep all of the value array nodes, which we can pop and check for maxValue.
public class BTree {
private final Node root;
public BTree(Node root) {
this.root = root;
}
public int getMaxKey() {
int maxKey = root.key;
Stack<Node> stack = new Stack<>();
stack.addAll(Arrays.asList(root.child));
while(!stack.isEmpty()){
Node node = stack.pop();
System.out.println(node.key);
if(node.key > maxKey)
maxKey = node.key;
if(node.child != null)
stack.addAll(Arrays.asList(node.child));
}
return maxKey;
}
}
Edit: I've created a image which can help us to understand the tree little bit more clearly, and i've used for my reference for this code.
My solution without Stack object:
public int getMaxKey() {
Node copy = root;
int max = -1;
while (copy.child != null) {
if (max < copy.key)
max = copy.key; //root
if (copy.child.length == 1) { // max key between parent and child node, only one path available
if (max < copy.child[0].key) {
max = copy.child[0].key;
copy = copy.child[0];
}
} else if (copy.child.length == 2) { // max between two nodes, decide between one path
int maxBetweenChild = Math.max(copy.child[0].key, copy.child[1].key);
Node node = Arrays.stream(copy.child).filter(n -> n.key == maxBetweenChild).findFirst().get();
copy = node;
if (max < maxBetweenChild)
max = maxBetweenChild;
}
}
return max;
}
This question already has answers here:
inserting in binary tree doesn't work using java
(2 answers)
Closed 2 years ago.
class bTree {
public class Node {
Node left;
Node right;
int val;
Node () {}
Node (int val){
this.val=val;
}
}
Node root;
public void insert(int val){
if (root == null){
root = new Node(val);
} else {
Node current = root;
// If val less than parent node's val go left
if (val <= root.val){
if (root.left == null){
root.left = new Node(val);
} else {
insert(val);
}
}
// If val greater than parent node's val go right
else {
if (root.right == null){
root.right = new Node(val);
} else {
insert(val);
}
} // inner else ends
} // outer else ends
} // insert() ends
public void displayTree(Node root){
if (root.left != null){
displayTree(root.left);
}
System.out.print(root.val + " - ");
if (root.right != null){
displayTree(root.right);
}
}
public static void main(String[] args) {
bTree bt = new bTree();
bt.insert(10);
bt.insert(30);
bt.insert(4);
bt.insert(5);
bt.displayTree(bt.root);
}
}
I was trying to implement a binary search tree and came across a problem inserting values in it. I have implemented it before making a Node main class but now nesting a Node class inside of a main class (like a LinkedList) is complicating it.
public void insert(int val){
if (root == null){
root = new Node(val);
} else {
Node current = root;
Here in this bit current is always getting value of root which causes not more than 3 items to be inserted. I am aware of this problem but couldn't get around it. Any redesign in the code would be greatly appreciated.
In your code you are not passing the reference of Node in insert() method to trace down at which node position you are in the current tree.
Currently you are able to insert only 3 items because for 3 items no recursion of insert(val) is getting used, but after 3 items you are using recursion of insert call and since in that you are not passing current node position this issue is coming.
Here is the working example of insertion in binary tree :
class bTree {
Node root;
public class Node {
Node left;
Node right;
int val;
Node () {}
Node (int val){
this.val=val;
}
}
public void insert(Node currnode, int val){
if(currnode == null) {
root = new Node(val);
return;
}
if(val <= currnode.val) {
if(currnode.left == null) {
currnode.left = new Node(val);
} else {
insert(currnode.left, val);
}
} else {
if(currnode.right == null) {
currnode.right = new Node(val);
} else {
insert(currnode.right, val);
}
}
}
public void displayTree(Node root){
if (root.left != null){
displayTree(root.left);
}
System.out.print(root.val + " - ");
if (root.right != null){
displayTree(root.right);
}
}
public static void main(String[] args) {
bTree bt = new bTree();
bt.insert(bt.root,10);
bt.insert(bt.root,30);
bt.insert(bt.root,4);
bt.insert(bt.root,5);
bt.displayTree(bt.root);
}
}
I'm doing a homework assignment in Java where I have to create an unsorted binary tree with a String as the data value. I then have to write a function that replaces a Node and any duplicate Nodes that match an old description with a new object that contains a new description.
Here is the code that I am working with, including the test case that causes an infinite loop:
public class Node {
private String desc;
private Node leftNode = null;
private Node rightNode = null;
private int height;
public Node(String desc) {
this.desc = desc;
height = 0; // assumes that a leaf node has a height of 0
}
public String getDesc() {
return desc;
}
public Node getLeftNode() {
return leftNode;
}
public Node getRightNode() {
return rightNode;
}
public void setLeftNode(Node node) {
++height;
leftNode = node;
}
public void setRightNode(Node node) {
++height;
rightNode = node;
}
public int getHeight() {
return height;
}
public int addNode(Node node) {
if(leftNode == null) {
setLeftNode(node);
return 1;
}
if(rightNode == null) {
setRightNode(node);
return 1;
}
if(leftNode.getHeight() <= rightNode.getHeight()) {
leftNode.addNode(node);
++height;
} else {
rightNode.addNode(node);
++height;
}
return 0;
}
public static void displayTree(Node root) {
if(root != null) {
displayTree(root.getLeftNode());
System.out.println(root.getDesc());
displayTree(root.getRightNode());
}
}
public static Node findNode(Node current, String desc) {
Node result = null;
if(current == null) {
return null;
}
if(current.getDesc().equals(desc)) {
return current;
}
if(current.getLeftNode() != null) {
result = findNode(current.getLeftNode(), desc);
}
if(result == null) {
result = findNode(current.getRightNode(), desc);
}
return result;
}
public static void replaceNode(Node root, String oldDesc, String newDesc) {
if(oldDesc == null || newDesc == null) {
System.out.println("Invalid string entered");
return;
}
boolean replacedAllNodes = false;
while(replacedAllNodes == false) {
Node replace = findNode(root, oldDesc);
if(replace == null) { // No more nodes to replace
replacedAllNodes = true;
return;
}
replace = new Node(newDesc);
root.addNode(replace);
}
return;
}
public static void main(String[] args) {
Node root = new Node("test1");
Node test_2 = new Node("test2");
Node test_3 = new Node("test3");
Node test_4 = new Node("test4");
Node test_5 = new Node("test5");
Node test_6 = new Node("test6");
root.addNode(test_2);
root.addNode(test_3);
root.addNode(test_4);
root.addNode(test_5);
root.addNode(test_6);
displayTree(root);
replaceNode(root, "test4", "hey");
System.out.println("-------");
displayTree(root);
}
}
After testing the findNode method, and seeing that it returns the correct object, I realized that the infinite loop was being caused by my replaceNode method. I'm just not really sure how it is causing it.
I got it to work with one case by removing the while loop, but obviously that won't work for duplicates, so I'm wondering how I could remove the node with oldDesc and replace it with a new object that contains newDesc when there could be multiple objects with matching oldDesc data.
you are never changing root or oldDesc in your while loop
while(replacedAllNodes == false) {
Node replace = findNode(root, oldDesc);
if(replace == null) { // No more nodes to replace
replacedAllNodes = true;
return;
}
replace = new Node(newDesc);
root.addNode(replace);
}
If you watch
public static Node findNode(Node current, String desc) {
Node result = null;
if(current == null) {
return null;
}
if(current.getDesc().equals(desc)) {
return current;
}
if(current.getLeftNode() != null) {
result = findNode(current.getLeftNode(), desc);
}
if(result == null) {
result = findNode(current.getRightNode(), desc);
}
return result;
}
If the if(current.getDesc().equals(desc)) condition matches, replace will always be root so you are stuck in your while loop
Update:
If you dont necessarily have to replace the whole node, you could just update the description for your node at the end of your while loop.
instead of
replace = new Node(newDesc);
root.addNode(replace);
do something like:
root.setDesc(newDesc);
(of course you would have to create a setDesc() method first)
If you have to replace the whole object, you have to go like this:
Instead of
replace = new Node(newDesc);
root.addNode(replace);
do something like this:
replace = new Node(newDesc);
replace.setLeftNode(root.getLeftNode);
replace.setRightNode(root.getRightNode);
Plus you have to link the node that pointed to root so it points to replace like one of the following examples (depends on which side your root was of course):
nodeThatPointedToRoot.setLeftNode(replace);
nodeThatPointedToRoot.setRightNode(replace);
well looking at your code, you are not replacing a node you are just adding a new node to the edge of the tree and the old node would still be there so the loop will go forever and you can add a temp variable with an auto increment feature and to indicate the level of the node you are reaching to replace and you'll find it's just doing it again and again, instead of doing all this process how about just replacing the description inside that node ?
Iterator words = treeSearch.getItems().iterator();
int addCount = 0;
while (words.hasNext())
{
numWords++;
rootNode = add(objectToReference, addCount++, (ITreeSearch) words.next(), 0, rootNode);
}
//Add to the Tree
private TernaryTreeNode add(Object storedObject, int wordNum, ITreeSearch treeSearch, int pos, TernaryTreeNode parentNode) throws NoSearchValueSetException
{
if (parentNode == null)
{
parentNode = new TernaryTreeNode(treeSearch.getNodeValue(pos));
}
if (parentNode.lessThan(treeSearch, pos))
{
parentNode.left = add(storedObject, wordNum, treeSearch, pos, parentNode.left);
}
else if (parentNode.greaterThan(treeSearch, pos))
{
parentNode.right = add(storedObject, wordNum, treeSearch, pos, parentNode.right);
}
else
{
if (pos < treeSearch.getNumberNodeValues())
{
parentNode.mid = add(storedObject, wordNum, treeSearch, pos + 1, parentNode.mid);
}
else
{
numberOfObjectsStored++;
parentNode.addStoredData(storedObject);
}
}
return parentNode;
}
This a snippet of my code in my Ternary Tree which I use for inserting a Name of a person(can hav multiple words in a name, like Michele Adams, Tina Joseph George, etc). I want to convert the above recursion to a for loop / while iterator.
Please guide me on this.
General idea in replacing recursion with iteration is to create a state variable, and update it in the loop by following the same rules that you follow in your recursive program. This means that when you pick a left subtree in the recursive program, you update the state to reference the left subtree; when you go to the right subtree, the state changes to reference the right subtree, and so on.
Here is an example of how to rewrite the classic insertion into binary tree without recursion:
public TreeNode add(TreeNode node, int value) {
// Prepare the node that we will eventually insert
TreeNode insert = new TreeNode();
insert.data = value;
// If the parent is null, insert becomes the new parent
if (node == null) {
return insert;
}
// Use current to traverse the tree to the point of insertion
TreeNode current = node;
// Here, current represents the state
while (true) {
// The conditional below will move the state to the left node
// or to the right node, depending on the current state
if (value < current.data) {
if (current.left == null) {
current.left = insert;
break;
} else {
current = current.left;
}
} else {
if (current.right == null) {
current.right = insert;
break;
} else {
current = current.right;
}
}
}
// This is the original node, not the current state
return node;
}
Demo.
Thanks dasblinkenlight..
This is my logic for replacing the above recursive function for a ternary tree.
Iterator words = treeSearch.getItems().iterator();
while (words.hasNext())
{
for (int i = 0; i < word.getNumberNodeValues(); i++)
{
add_Non_Recursive(objectToReference, word, i);
}
}
//Add to Tree
private void add_Non_Recursive(Object storedObject, ITreeSearch treeSearch, int pos) throws NoSearchValueSetException
{
TernaryTreeNode currentNode = rootNode;
// Start from a node(parentNode). If there is no node, then we create a new node to insert into the tree.
// This could even be the root node.
if (rootNode == null)
{
rootNode = new TernaryTreeNode(treeSearch.getNodeValue(pos));
}
else
{
while (currentNode != null)
{
if (currentNode.lessThan(treeSearch, pos))
{
if (currentNode.left == null)
{
currentNode.left = new TernaryTreeNode(treeSearch.getNodeValue(pos));
currentNode = null;
}
else
{
currentNode = currentNode.left;
}
}
else if (currentNode.greaterThan(treeSearch, pos))
{
if (currentNode.right == null)
{
currentNode.right = new TernaryTreeNode(treeSearch.getNodeValue(pos));
currentNode = null;
}
else
{
currentNode = currentNode.right;
}
}
else
{
if (currentNode.mid == null)
{
currentNode.mid = new TernaryTreeNode(treeSearch.getNodeValue(pos));
currentNode = null;
}
else
{
currentNode = currentNode.mid;
}
}
}
}
}
But I dropped this logic as it wasnt great in performing, it took more time than the recursive counterpart.
I'm trying to write code for a binary search tree, the first method I'm working on is the add (insert) method. The root seems to insert properly, but I'm getting null pointer exception when adding the second node. I'll indicate the exact problem spot in my code with comments.
If you can see how to fix the bugs, or let me know if my overall logic is flawed it would be incredibly helpful.-- I will mention that this is for school, so I'm not looking to make a really impressive model...most of my layout choices simply reflect the way we've been working in class. Also, method names were selected by the teacher and should stay the same. Feel free to edit the formatting, had a little trouble.
BINARY TREE CLASS
public class BinarySearchTree
{
private static Node root;
public BinarySearchTree()
{
root = null;
}
public static void Add (Node newNode)
{
Node k = root;
if (root == null)//-----------------IF TREE IS EMPTY -----------------
{
root = newNode;
}
else // -------TREE IS NOT EMPTY --------
{
if (newNode.value > k.value) //-------NEW NODE IS LARGER THAN ROOT---------
{
boolean searching = true;
while(searching) // SEARCH UNTIL K HAS A LARGER VALUE
{ //***CODE FAILS HERE****
if(k.value > newNode.value || k == null)
{
searching = false;
}
else {k = k.rightChild; }
}
if ( k == null) { k = newNode;}
else if (k.leftChild == null){ k.leftChild = newNode;}
else
{
Node temp = k.leftChild;
k.leftChild = newNode;
newNode = k.leftChild;
if(temp.value > newNode.value )
{
newNode.rightChild = temp;
}
else
{
newNode.leftChild = temp;
}
}
}
if (newNode.value < k.value) //-----IF NEW NODE IS SMALLER THAN ROOT---
{
boolean searching = true;
while(searching) // ----SEARCH UNTIL K HAS SMALLER VALUE
{// **** CODE WILL PROBABLY FAIL HERE TOO ***
if(k.value < newNode.value || k == null) {searching = false;}
else {k = k.leftChild;}
}
if ( k == null) { k = newNode;}
else if (k.rightChild == null){ k.rightChild = newNode;}
else
{
Node temp = k.rightChild;
k.rightChild = newNode;
newNode = k.rightChild;
if(temp.value > newNode.value )
{
newNode.rightChild = temp;
}
else
{
newNode.leftChild = temp;
}
}
}
}} // sorry having formatting issues
}
NODE CLASS
public class Node
{
int value;
Node leftChild;
Node rightChild;
public Node (int VALUE)
{
value = VALUE;
}
}
TEST APPLICATION
public class TestIT
{
public static void main(String[] args)
{
BinarySearchTree tree1 = new BinarySearchTree();
Node five = new Node(5);
Node six = new Node(6);
tree1.Add(five);
tree1.Add(six);
System.out.println("five value: " + five.value);
System.out.println("five right: " + five.rightChild.value);
}
}
The conditional statement is checked from left to right, so you need to check whether k is null before you check whether k.value > newNode.value because if k is null, then it doesn't have a value.