I am trying to build an algorithm to find a node's successor, by recursively calling the following :
public static BTreeNode inorderFirst(BTree T) {
BTreeNode n = T.getRoot();
if (n == null)
return null;
while (n.getLeftChild() != null)
n = n.getLeftChild();
return n;
}
And calling this
public static BTreeNode inorderNext(BTreeNode n) {
//returns successor. if it finds one.
// TODO
// if node has a right child get its left descendant.
// otherwise get the first ancestor of which in the left sub-tree the node n is.
// if it didn't find
return null;
} // inorderNext()
I am using custom imports which have methods for getting getLeftChild(), and so on also has getParent() which aren't too hard to figure out. If anyone has any ideas on how to start building this. I have added some comments of my own plan. I just don't know how to start executing. I would like the structure because it makes it easier to test the method.
I figured out a way to make it work without using the recursion:
public static BTreeNode inorderNext(BTreeNode n) {
if (n.getRightChild() != null) {
BTreeNode temp = n.getRightChild();
while (temp.getLeftChild() != null)
temp = temp.getLeftChild();
return temp;
}
else {
BTreeNode temp = n;
BTreeNode par = n.getParent();
while (par != null) {
if (par.getLeftChild() == temp)
return par;
else {
temp = par;
par = par.getParent();
}
}
}
return null;
} // inorderNext()
But i am still wondering if there was a way to use the first function recursively on this one.
Your code would be something like the following:
if(n.getLeftChild() != null)
inorderNext(n.getLeftChild());
System.out.print(n.data);
if(n.getRightChild() != null)
inorderNext(n.getRightChild());
Related
I've written a remove function for a binary search tree that uses a while loop to navigate to the specific node to be removed. However, it's never getting there - it just iterates an unknown number of times and then gives me a NullPointerException.
I was wondering if it was an error in my traversal logic, but it's exactly the same as in my add function, which works perfectly.
void remove(Comparable newObject){
if (!isEmpty()){
Node curr = new Node();
curr = root;
boolean isFound = false;
while (!isFound){
if (curr.data.compareTo(newObject) == 0){
if (curr.hasChildren()){
Node replaceNode = new Node();
if (curr.leftChild == null){
replaceNode = curr.rightChild;
while (replaceNode.leftChild != null){
replaceNode = replaceNode.leftChild;
}
} else {
replaceNode = curr.leftChild;
while (replaceNode.rightChild != null) {
replaceNode = replaceNode.rightChild;
}
}
replaceNode.leftChild = curr.leftChild;
replaceNode.rightChild = curr.rightChild;
replaceNode.parent = curr.parent;
curr = replaceNode;
} else {
curr.data = null;
curr.parent = null;
}
listSize--;
isFound = true;
} else if (curr.data.compareTo(newObject) == 1) {
curr = curr.leftChild;
} else {
curr = curr.rightChild;
}
}
}
}
The data set I'm using yields a root with a left child, and then a right child off of that. The node to be removed is the first (left) child. However, the line that's giving the NullPointerException is
if (curr.data.compareTo(newObject) == 0){
and I'm really not sure at all what's causing this. Any and all help is appreciated greatly.
First of all don't initialize the variable as a new Node(), you're creating new Nodes you're not gonna use. Do it more like this:
void remove(Comparable newObject){
if (!isEmpty()){
Node curr = root;
and then again your replaceNode:
if (curr.hasChildren()){
Node replaceNode;
and I think it's not working, because in the end of the code, you rewrite curr to its children, but what if it doesn't have children? Then you try to compare null object with some object and that's why I think it throws NullPointerException.
I have written a recursive program for checking whether a binary tree is a BST.
I have written a base case which is returning true or false, but I have got confused in recursive case.
This program makes the recursive call but it is not working though I feel its fine.
public class BinaryBSTChecker {
public static boolean isBinaryBST(Node node) {
if ( node != null) {
Node leftNode = node.getLeftNode();
Node rightNode = node.getRightNode();
int value = node.getValue();
isBinaryBST(leftNode) ;
isBinaryBST(rightNode) ;
boolean leftIsOk = isLeftOK(leftNode , value);
boolean rightIsOk = isRightOK(rightNode, value);
return (leftIsOk && rightIsOk);
}
return false;
}
private static boolean isLeftOK(Node leftNode, int value) {
boolean leftOK = false;
if (leftNode != null) {
if (leftNode.getValue() < value) {
leftOK = true;
}
} else {
leftOK = true;
}
return leftOK;
}
private static boolean isRightOK(Node rightNode, int value) {
boolean rightOK = false;
if (rightNode != null ) {
if (rightNode.getValue() > value) {
rightOK = true;
}
} else {
rightOK = true;
}
return rightOK;
}
}
Client code:
public class TestingClient {
public static void main (String[] args) {
Node node = getBSTTree() ;
System.out.println("------Is Binary BST ?------>"
+ BinaryBSTChecker.isBinaryBST(node));
}
public static Node getBSTTree() {
Node node = new Node(9);
Node leftNode = new Node(7);
Node rightNode = new Node(11);
Node leftNode2 = new Node(67);
Node rightNode2 = new Node(8);
Node leftNode3 = new Node(10);
Node rightNode3 = new Node(12);
node.setLeftNode(leftNode);
node.setRightNode(rightNode);
leftNode.setLeftNode(leftNode2);
leftNode.setRightNode(rightNode2);
rightNode.setLeftNode(leftNode3);
rightNode.setRightNode(rightNode3);
return node;
}
}
The above tree isn't a BST as 67 > 7.
So this should return false, but I am getting true for this case, and in fact for all cases.
why are you returning false at end of public static boolean isBinaryBST(Node node) ?
Return true there and should be ok.
edit:
obviously it was a mistake but i did not take a good look at code.
One more thing here.
There is only isLeftOK and isRightOk called, but also on left & right nodes but there are also calls
isBinaryBST(leftNode) ;
isBinaryBST(rightNode);
It seems that results of those are ignored and this is an issue.
return should be sth like:
return (leftIsOk && rightIsOk && isBinaryBST(leftNode) && isBinaryBST(rightNode));
You're ignoring the return value of isBinaryBST in the recursive calls, so the function just returns whether the root's children is correct.
But the way you tried to solve the problem fundamentally won't work.
Take this tree:
5
/
3
\
7
It's not a valid BST, as 7 > 5.
There's no way you can check for this by only looking at the direct children.
The recommended approach would be passing in a min and max to your function, i.e. the signature would be:
boolean isBinaryBST(Node node, int min, int max)
And simply checking whether the current node's value is between the two (or the node is null) (no need for helper functions), and making the appropriate recursive calls to the children (and remember to check their return values!). The general idea would be: (pseudo-code)
return (current node is between min and max)
&& (left subtree is okay, i.e. recursive call with left child)
&& (right subtree is okay, i.e. recursive call with right child)
I'll leave the exact details to you to work out.
In the above example, when we get to 7, min = 3 and max = 5, so we see that 7 > max, and return false.
Add null checks or it will go in infinite loop
if(leftNode != null)
isBinaryBST(leftNode) ;
if(rightNode != null)
isBinaryBST(rightNode) ;
boolean leftIsOk = true;
boolean rightIsOk = true;
if(leftNode != null)
leftIsOk = isLeftOK(leftNode , value); ;
if(rightNode != null)
rightIsOk = isRightOK(rightNode, value);
return (leftIsOk && rightIsOk);
First off, this is homework, so putting that out there.
I'm supposed to implement a binary search tree with specific methods:
void insert(String), boolean remove(String), and boolean find (String).
I have been able to successfully program and test the insert and find methods but am having difficulty with the remove.
What is going on in my program is the remove isn't actually removing anything from the tree and I believe this is because its only referencing the local creation of the current node but I could be wrong. I think I can implement the logic of the different cases I need to test (might need help with the deleting a node with two children case but I think I get it conceptually) am mainly trying to understand what I need to do differently to reference the tree properly in the
current = null; // case
Here is what I got so far:
public boolean remove(String title)
{
return remove(root, title);
}
private boolean remove(BSTNode current, String title)
{
if (current == null)
{
return false;
}
if (current.data == title)
{
if (current.left_child !=null && current.right_child != null)
{
return true; // returning true since I haven't finished writing this case
}
else if (current.left_child == null && current.right_child == null)
{
current = null; // this should remove the node from tree but it doesn't
return true;
}
else if (current.left_child != null && current.right_child == null)
{
current = current.left_child; // don't think this is right
return true;
}
else if (current.right_child != null && current.left_child == null)
{
current = current.right_child; // not sure about this
return true;
}
}
root = current;
if (title.compareToIgnoreCase(current.data) == -1)
{
return remove(current.left_child, title);
}
else
{
return remove(current.right_child, title);
}
}
Any knowledge is much appreciated.
A node is referenced by it's parent (except for the root, that node is referenced by your BST itself). In order to remove a node from the tree, you need to set that reference in the parent node to null.
What you're trying to do now is something like:
Before:
parent.left ---> node <--- current
After setting current = null:
parent.left ---> node current ---> null
that is, current references null, but that does not change the parent (only that local variable).
In your remove method you need to pass the parent along as well (or handle both children in the call for the parent, whatever you like better).
By the way: never, ever compare strings with ==, see for instance this question.
How to find the node and it's parent without explicitly storing the parent in each node:
I would say it is simpler to do this in a loop, rather than with recursion, but both would work. In a loop:
BSTNode parent = null;
BSTNode current = root;
boolean found = false;
while (!found && current != null) {
int compare = title.compareToIgnoreCase(current.data);
if (compare == 0) {
found = true;
} else {
parent = current;
if (compare < 0) {
current = current.left;
} else {
current = current.right;
}
}
}
if (!found) {
// title was not found
} else if (parent == null) {
// found the root
} else {
// found another node
}
By recursion is annoying, because you want a method that returns both the node and it's parent. You will need some simple inner class to solve this:
private class NodeAndParent {
public BSTNode node;
public BSTNode parent;
public NodeAndParent(BSTNode node, BSTNode parent) {
this.node = node;
this.parent = parent;
}
}
private boolean find(String title, NodeAndParent current) {
if (current.node == null) {
return false; // not found
} else {
int compare = title.compareToIgnoreCase(current.node.data);
if (compare == 0) {
return true; // found
} else {
current.parent = current.node;
if (compare < 0) {
current.node = current.node.left;
} else {
current.node = current.node.right;
}
}
}
}
private boolean remove(String title) {
NodeAndParent nodeAndParent = new NodeAndParent(root, null);
boolean found = find(title, nodeAndParent);
if (!found) {
// title was not found
} else if (nodeAndParent.parent == null) {
// found the root
} else {
// found another node
}
}
After what #hyde told me, this is what I did:
Node<E> current = root;
int count = 0;
public int getNumberOfInteriorNodes() {
if (current == null || (current.left == null && current.right == null)) {
return count;
}
else {
if (current.right != null) {
Node<E> tmp = current;
current = current.right;
count += getNumberOfInteriorNodes();
current = tmp;
}
if (current.left != null) {
Node<E> tmp = current;
current = current.left;
count += getNumberOfInteriorNodes();
current = tmp;
}
return count + 1;
}
}
Below is what my test method looks like:
public static void testGetNumberOfInteriorNodes() {
BinarySearchTree<Integer> t;
t = new BinarySearchTree<Integer>();
Assert.assertEquals(0, t.getNumberOfInteriorNodes());
t.add(2);
Assert.assertEquals(0, t.getNumberOfInteriorNodes());
t.add(1);
Assert.assertEquals(1, t.getNumberOfInteriorNodes());
t.add(5);
Assert.assertEquals(1, t.getNumberOfInteriorNodes());
t.add(4);
Assert.assertEquals(2, t.getNumberOfInteriorNodes());
t.add(3);
Assert.assertEquals(3, t.getNumberOfInteriorNodes());
t.add(6);
Assert.assertEquals(3, t.getNumberOfInteriorNodes());
}
My test fails at the 3rd assertion with the error. Count never goes above zero. Here is the error I get:
Failure: junit.framework.AssertionFailedError: expected:<1> but was:<0>
Any further help would be appreciated.
Your problem is, you have just one shared current variable when you are using recursion. It will get overwritten in recursive calls. Instead, you must pass it as parameter, so your recursive function needs to be:
public int getNumberOfInteriorNodes(Node<E> current)
And on first call (somewhere else in your code) you pass root to it:
... = getNumberOfInteriorNodes(root);
Then you need to pass modified value in recursive call, for right side:
count += getNumberOfInteriorNodes(current.right);
And same for left side, naturally. No return here, otherwise it would return and not calculate the other side! Also no +1, if both right and left side exist then it would be +2. Instead, return count + 1; at the end of the method (yep, you do need it).
Also, in your first if, no point testing if root == null, it does not do anything useful (nothing harmful either in this case, but it's still clutter which makes it harder understand the code, and may become a problem if you change the code).
Then you also seem to have this: int count==0;;
Does that even compile, or is it a copy-paste error? You should use assignment int count = 0;
If you have limitation of not having parameters for the method, you need to restore value of current after the call. Here's code for the right side, do same for the left side:
if (current.right!=null) {
Node<E> tmp = current;
current = current.right;
count += getNumberOfInteriorNodes();
current = tmp;
}
Note that for "real" code, this would be quite a stupid way to do recursion.
If this "no parameters" is just API limitation, then the usual way to solve this is with a private helper method:
public int getNumberOfInteriorNodes() {
return recNumberOfInteriorNodes(root)
}
private int recNumberOfInteriorNodes(Node<E> current) {
...
}
Here's some code that does the trick. Btw: Nodes with no children are leaves.
class Node {
Node left;
Node right;
}
class Main {
void test() {
Node root = new Node();
Node leftleft = new Node();
Node left = new Node();
Node right = new Node();
Node rightright = new Node();
Node rightleft = new Node();
root.left = left;
root.right = right;
left.left = leftleft;
right.left = rightleft;
right.right = rightright;
int c = getLeaves(root);
}
int getLeaves(Node node) {
if (node == null)
return 0;
if (node.left == null && node.right == null)
return 1;
return getLeaves(node.left) + getLeaves(node.right);
}
}
I have implemented a class for "first child next sibling" tree in java.
Here is a link representing such a tree
http://www.cs.utexas.edu/~novak/cs315116.html
I have implemented the following functions:
addChild();
getLabel();
setLabel(T v);
getParent();
getNextSibling();
getFirstChild();
My addChild functions adds the children in the following order.
public void addChild(Tree<T> c) {
c.parent = this;
if (firstChild == null)
firstChild = c;
else {
c.nextSibling = firstChild;
firstChild = c;
}
}
That is, if we have a tree node 1 and we add tree node 2 and then tree node 3 to it then the final tree would be,
1.addChild(2);
1.addChild(3);
1 1
/ \ which is internally stored as /
3 2 3 - 2
The most recent child added would be the first child
I want to implement a CopyTree function which, when given any such tree as an argument will create a copy of the tree and return it.
I have some initial code but I am unable to get the correct recursion.
private Tree<String> CopyTree(Tree<String> tr){
if (tr == null)
return null;
Tree<String> t = new Tree<String>();
t.setLabel(tr.getLabel());
if (tr.getFirstChild() != null) {
t.addChild(CopyTree(tr.getFirstChild()));
}
Tree<String> temp = tr.left();
if (temp != null) {
while (temp.getNextSibling() != null) {
t.addChild(CopyTree(temp.getNextSibling()));
temp = temp.getNextSibling();
}
}
return t;
}
What to do in order to make the recursion work??
Thanks in advance
First of all, I believe you have an error here:
while (temp.getNextSibling() != null) {
t.addChild(CopyTree(temp.getNextSibling()));
temp = temp.getNextSibling();
}
Since getNextSibling() retuns the next children to the right, but addChild() inserts a children from the left, you are reversing the order here. This might be ok, but try to avoid this.
To answer your question, your recursion function should be called as a method on each node of the new Tree and receive the corresponding node of the old tree as an argument. It should then copy the children of this node from the old tree in the new one and, while doing this, call the recursion function on each of these children.
Got it..
private Tree<String> CopyTree(Tree<String> tr){
if (tr == null)
return null;
Tree<String> t = new Tree<String>();
t.setLabel(tr.getLabel());
Tree<String> temp = tr.left();
if (temp != null) {
ArrayList<Tree<String>> list = new ArrayList<>();
while (temp.getNextSibling() != null) {
list.add(temp.getNextSibling());
//t.addChild(CopyTree(temp.getNextSibling()));
temp = temp.getNextSibling();
}
for (int i = (list.size()-1); i>=0; i--) {
t.addChild(CopyTree(list.get(i)));
}
}
if (tr.left() != null) {
t.addChild(CopyTree(tr.left()));
}
return t;
}