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.
Related
so currently I’m trying to follow a tutorial from FreeCodeCamp on implementing a Binary tree, but I’m having trouble with adding to and traversing through my tree.
For some reason, it seems that I’m able to add nodes to my tree, but when I try to traverse through my tree via iterative preorder traversal, it only picks up my root node. Its as if my nodes aren’t pointing to each other.
I have a feeling that the problem either lies with my add method or my traversal method, both of which are below. Any help would be greatly appreciated.
Add method:
public boolean add(T thing)
{
if(contains(thing))
{
return false;
} else {
root = add(root,thing);
count++;
return true;
}
}
private Node add(Node node,T thing)
{
if(node == null)
{
node = new Node(thing,null,null);
} else
{
if(thing.compareTo(node.value) <0)
{
if(node.left == null)
{
node.left = node = new Node(thing,null,null);
} else{
node.left =add(node.left,thing);
}
}
else
{
if(node.right == null)
{
node.right = node = new Node(thing,null,null);
}else {
node.right = add(node.right,thing);
}
}
}
return node;
}
Traversal:
public void traverse()
{
preorder(root);
}
private void preorder(Node node)
{ int iteration=0;
java.util.Stack<Node> stack = new java.util.Stack<Node>();
System.out.println( "root is: " +node.value);
stack.push(node);
while(stack.empty() == false)
{
Node current = stack.pop();
System.out.println("in preorder: "+current.value);
if(current.right != null)
{
stack.push(current.right);
}
if(current.left != null)
{
stack.push(current.left);
}
iteration++;
}
System.out.println("iteration: "+iteration);
}
You are not traversing your tree while adding in the tree. Check my tree insert method to get the idea:-
void insert(Node temp,int value) {
if(temp==null){
temp=new Node(value,null,null);
this.root=temp;
}
else{
Queue<Node> q = new LinkedList<>();
q.add(temp);
while (!q.isEmpty()) {
temp = q.peek();
q.remove();
if (temp.left == null) {
temp.left = new Node(value, null, null);
break;
} else
q.add(temp.left);
if (temp.right == null) {
temp.right =new Node(value, null, null);
break;
} else
q.add(temp.right);
}
}
}
So i have 3 methods 1 that adds a node to the binary tree using the traverseAdd method, and another method which finds the location of where a value would be placed within the tree based on its parent node. I would like to eliminate the traverseAdd method and use the findLocation method within the add method to add the new value to the BST.
public void add(int val) {
/*Adds a new node to the binary tree after traversing the tree and figuring out where it belongs*/
Node nodeObjToAdd = new Node(val);
if(root == null){
//if node root is not null root = new node value
root = nodeObjToAdd;
}
Node nodeTraversed = root;
traverseAdd(nodeTraversed, nodeObjToAdd);
}
private void traverseAdd(Node node, Node nodeObjToAdd){
/*Traverses tree and finds a place to add the node to be added by comparing values of the left child and right child of the
* focus node*/
if(nodeObjToAdd.value < node.value){
if(node.leftChild == null){
node.leftChild = nodeObjToAdd;
}
else {
//if the val < the root.value set int he constructor
traverseAdd(node.leftChild, nodeObjToAdd);
}
}
else if(nodeObjToAdd.value > node.value) {
if (node.rightChild == null) {
node.rightChild = nodeObjToAdd;
} else {
traverseAdd(node.rightChild, nodeObjToAdd);
}
}
}
public Node findNodeLocation(Node rootNode, int val) {
/*returns where a the Node after which the value would be added.*/
if(val < rootNode.value && rootNode.leftChild != null){
return rootNode.leftChild;
}
if(val >= rootNode.value && rootNode.rightChild != null){
return rootNode.rightChild;
}
else
return this.root;
}
public void add(int val) {
if (root == null) {
root = new Node(val);
}
Node cur = root;
Node next = null;
while (true) {
next = findNodeLocation(cur, val);
if (next != cur) {
cur = next;
} else {
break;
}
}
if (val < cur.value) {
cur.leftChild = new Node(val);
} else {
cur.rightChild = new Node(val);
}
}
I think this should work
I am trying to implement leafCount() and nodeCount() to this recursive binary tree - program.
When testing it, these two methods (or the tests of them) throw AssertionError, so obviously they're not working as expected. I cannot figure out where I'm doing or thinking wrong. If someone could explain what I'm doing wrong or pinpoint the problem, I would be very grateful.
public class BSTrec {
BSTNode tree, parent, curr;
public BSTrec () {
tree = null; // the root of the tree
parent = null; // keeps track of the parent of the current node
curr = null; // help pointer to find a node or its place in the tree
}
public boolean isEmpty() {
return tree == null;
}
private boolean findNodeRec(String searchKey, BSTNode subtree, BSTNode subparent) {
if (subtree == null) { // base case 1: node not found
curr = null;
parent = subparent; // the logical parent for the value
return false;
}
else {
if (subtree.info.key.equals(searchKey)) {
curr = subtree; // update current to point to the node
parent = subparent; // update parent to point to its parent
return true;
}
else {
if (searchKey.compareTo(subtree.info.key) < 0) {
return findNodeRec(searchKey, subtree.left, subtree);
}
else {
return findNodeRec(searchKey, subtree.right, subtree);
}
}
}
}
public NodeInfo retrieveNode(String searchKey) {
if (findNodeRec(searchKey, tree, null)) return curr.info;
else return null;
}
public void addRec(String keyIn, BSTNode subtree, BSTNode subparent, boolean goLeft) {
if (tree == null) { // a first node will be the new root: base case 1
tree = new BSTNode(new NodeInfo(keyIn));
curr = tree;
parent = null;
}
else { // insertion in an existing tree
if (subtree == null) {
if (goLeft) {
subparent.left = new BSTNode(new NodeInfo(keyIn));
curr = subparent.left;
parent = subparent;
}
else { // the new node is to be a left child
subparent.right = new BSTNode(new NodeInfo(keyIn));
curr = subparent.right;
parent = subparent;
}
}
else {
if (keyIn.compareTo(subtree.info.key) < 0) {
addRec(keyIn, subtree.left, subtree, true);
}
else {
addRec(keyIn, subtree.right, subtree, false);
}
}
}
}
public void deleteNode(String searchKey) {
boolean found = findNodeRec(searchKey, tree, null);
if (!found) // the key is not in the tree
System.out.println("The key is not in the tree!");
else {
if ((curr.left == null) && (curr.right == null))
if (parent == null)
tree = null;
else
if (curr == parent.left) // delete a left child
parent.left = null;
else // delete a right child
parent.right = null;
else // delete a node with children, one or two
if ((curr.left != null) && (curr.right != null)) { // two children
BSTNode surrogateParent = curr;
BSTNode replacement = curr.left;
while (replacement.right != null) {
surrogateParent = replacement;
replacement = replacement.right;
}
curr.info = replacement.info; // the information is copied over
if (curr == surrogateParent) {
curr.left = replacement.left; // curr "adopts" the left
replacement = null;
}
else {
surrogateParent.right = replacement.left;
replacement = null;
}
} // End: if two children
else { // delete a node with one child
if (parent == null)
if (curr.left != null)
tree = curr.left;
else
tree = curr.right;
else
if (curr == parent.left)
if (curr.right == null)
parent.left = curr.left;
else
parent.left = curr.right;
else
if (curr.right == null)
parent.right = curr.left;
else
parent.right = curr.right;
}
curr = null;
}
}
public void inOrder(BSTNode root) {
if (root != null) {
inOrder(root.left); // process the left subtree
System.out.println(root.info.key); // process the node itself
inOrder(root.right); // process the right subtree
}
}
public void preOrder(BSTNode root) {
if (root != null) { // implicit base case: empty tree: do nothing
System.out.println(root.info.key); // process the node itself
preOrder(root.left); // process the left subtree
preOrder(root.right); // process the right subtree
}
}
public void postOrder(BSTNode root) {
if (root != null) { // implicit base case: empty tree: do nothing
postOrder(root.left); // process the left subtree
postOrder(root.right); // process the right subtree
System.out.println(root.info.key); // process the node itself
}
}
public int nodeCount() {
int count = 0;
if (tree == null) {
count = 0;
//throw new NullPointerException();
}
else {
if (tree.left != null) {
count = 1;
count += tree.left.nodeCount();
}
if (tree.right != null) {
count = 1;
count += tree.right.nodeCount();
}
}
return count;
}
public int leafCount() {
int count = 0;
if (tree == null) {
return 0;
}
if (tree != null && tree.left == null && tree.right==null) {
return 1;
}
else {
count += tree.left.leafCount();
count += tree.right.leafCount();
}
return count;
}
private class BSTNode {
NodeInfo info;
BSTNode left, right;
BSTNode() {
info = null;
left = null;
right = null;
}
public int leafCount() {
// TODO Auto-generated method stub
return 0;
}
public int nodeCount() {
// TODO Auto-generated method stub
return 0;
}
BSTNode(NodeInfo dataIn) {
info = dataIn;
left = null;
right = null;
}
BSTNode(NodeInfo dataIn, BSTNode l, BSTNode r) {
info = dataIn;
left = l;
right = r;
}
}
}
public class NodeInfo {
String key; // add other fields as needed!
NodeInfo() {
key = null;
}
NodeInfo(String keyIn) {
key = keyIn;
}
}
Your nodeCount logic has an error :
if (tree.left != null) {
count = 1;
count += tree.left.nodeCount();
}
if (tree.right != null) {
count = 1; // here you initialize the count, losing the count of the left sub-tree
count += tree.right.nodeCount();
}
Change to
if (tree.left != null || tree.right != null) {
count = 1;
if (tree.left != null) {
count += tree.left.nodeCount();
}
if (tree.right != null) {
count += tree.right.nodeCount();
}
}
In your leafCount you are missing some null checks, since it's possible one of the children is null :
if (tree != null && tree.left == null && tree.right==null) {
return 1;
} else {
if (tree.left != null) // added check
count += tree.left.leafCount();
if (tree.right != null) // added check
count += tree.right.leafCount();
}
In here:
public int leafCount() {
int count = 0;
if (tree == null) {
return 0;
}
if (tree != null && tree.left == null && tree.right==null) {
return 1;
}
else {
count += tree.left.leafCount();
count += tree.right.leafCount();
}
return count;
}
you're not allowing for the possibility that tree.left is non-null but tree.right is null. In that case, you'll try to execute
count += tree.right.leafCount();
which will throw a NullPointerException.
I think you should also rethink what you're doing with your instance fields curr and parent. These really should be local variables in whatever method you need to use them in. A tree doesn't have a "current" node in any meaningful sense.
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.
My current insert method for my binary tree is not inserting to the right of any node that is the left child of its parent.
current code:
private BinaryTreeNode insert(BinaryTreeNode current, String word) {
if (current == null) {
current = new BinaryTreeNode(word);
} else {
if (word.compareToIgnoreCase(current.value) < 0) { // if smaller than current node
if (current.left != null) {
if (word.compareToIgnoreCase(current.left.value) < 0) {// check next node for lesser than,
current.left = (insert(current.left, word));
}
} else {
current.left = new BinaryTreeNode(word);// iff current node is end of tree
System.out.println(word + "left");
}
} else {
if (current.right != null) { // if larger than current node
current.right = (insert(current.right, word));
} else {
current.right = new BinaryTreeNode(word); // if current node is end of tree
System.out.println(word + "right");
}
}
}
return current;
}
Your problem lies here:
if (word.compareToIgnoreCase(current.left.value) < 0) {// check next node for lesser than,
current.left = (insert(current.left, word));
}
What are you expecting this to do? You already know you should be inserting to the left of the current node, but why are you re-checking the next node down here?
You should recurse instead of reaching down to compare to the left:
private static BinaryTreeNode insert(BinaryTreeNode current, String word) {
if (current == null) {
current = new BinaryTreeNode(word);
} else {
int test = word.compareToIgnoreCase(current.value);
if (test < 0) {
current.left = insert(current.left, word);
} else if (test > 0) {
current.right = insert(current.right, word);
}
// else word already at this node!
}
return current;
}
Note that the function should be static, since it doesn't depend on this.
I think there were some errors... I would do something like this:
private void insert(BinaryTreeNode current, String word) {
if (current == null) {
current = new BinaryTreeNode(word);
} else {
if (word.compareToIgnoreCase(current.value) < 0) {
if (current.left != null) {
insert(current.left, word);
} else {
current.left = new BinaryTreeNode(word);
System.out.println(word + "left");
}
} else {
if (current.right != null) {
insert(current.right, word);
} else {
current.right = new BinaryTreeNode(word);
System.out.println(word + "right");
}
}
}
}