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;
}
Related
I have an assignment:
You’re given the root node of a binary tree T. We distinguish between 3 types of nodes in T: nodes with 0 children, nodes with 1 child, and nodes with 2 children. Determine, for each type, the number of nodes in T. Return your result as an integer array of length 3.
I am given a Java file that generates random test cases for this algorithm.
I am only allowed to create one function to do all of this. I am not allowed to pass any additional parameters into the method below. I am also not allowed to make any other modifications outside of the function that I create.
In the file, there is a base case already inserted. I have been told to traverse the tree in post-order, using recursion.
I am aware of the current issues with my code. But I don’t know how to fix them.
My current code is as follows:
private static int[] problem1(Node root) {
int[] arr = new int[3];
if (root == null) {
return new int[] {
-1, // nodes with 0 children
-1, // nodes with 1 child
-1 // nodes with 2 children
};
}
//problem1(root.left);
//problem1(root.right);
if (root.left != null && root.right != null) {
arr[2]++;
problem1(root.left);
problem1(root.right);
} else if (root.left != null && root.right == null) {
arr[1]++;
problem1(root.left);
} else if (root.left == null && root.right != null) {
arr[1]++;
problem1(root.right);
} else {
arr[0]++;
}
return arr;
}
The Node class is defined as:
static class Node {
public int value;
public Node left;
public Node right;
}
class Playground {
public static void main(String[ ] args) {
Node root = new Node(1, new Node(2, null, null), new Node(3, null, null));
int[] counts = problem1(root);
System.out.println(counts[0]); // 2 node(s) with 0 children
System.out.println(counts[1]); // 0 node(s) with 1 children
System.out.println(counts[2]); // 1 node(s) with 2 children
}
// recursively count number of childs for each root/node. Post-order
// traversing means both left and right node will be traversed before
// any computations.
public static int[] problem1(Node root) {
// always need a base-case to stop recursive call.
if(root == null) {
return new int[]{0,0,0};
}
// post-order traversing
int[] leftChildCounts = problem1(root.left);
int[] rightChildCounts = problem1(root.right);
int [] counts = new int[]{0,0,0};
counts[0] = leftChildCounts[0] + rightChildCounts[0];
counts[1] = leftChildCounts[1] + rightChildCounts[1];
counts[2] = leftChildCounts[2] + rightChildCounts[2];
if(root.left == null && root.right == null) {
counts[0]++;
} else if(root.left != null && root.right != null) {
counts[2]++;
} else {
counts[1]++;
}
return counts;
}
}
public class Node {
int value;
Node left;
Node right;
public Node(int value, Node left, Node right) {
this.value = 0;
this.left = left;
this.right = right;
}
}
I think you've come pretty close, the only thing you should fix is handling the array of result.
Currently you create a new arr that is supposed to stored the results for every call of problem1 and its wrong because this new array has nothing to do with previously created arrays.
Consider to create it outside the call of problem1 method. You can always pass it as an additional parameter and "accumulate" the result (there is even a term called "accumulator" for this, so arr will be an accumulator).
Think also about the return result (hint: with the accumulator approach you don't really need to return anything)
Since its an assignment, obviously I won't give a full solution leaving to you all the fun ;)
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 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());
I need to create a recursive method that takes as a parameter the root node of a binary search tree. This recursive method will then return the int value of the total number of nodes in the entire binary search tree.
This is what I have so far:
public class BinarySearchTree<E> extends AbstractSet<E>
{
protected Entry<E> root;
//called by the main method
public int nodes()
{
return nodes(root);
}
//nodes() will count and return the nodes in the binary search tree
private int nodes(Entry<E> current)
{
if(current.element != null)
{
if(current.left == null && current.right == null)
{
if(current.element == root.element)
return 1;
deleteEntry(current);
return 1 + nodes(current.parent);
}
else if(current.left != null && current.right == null)
return nodes(current.left);
else if(current.left == null && current.right != null)
return nodes(current.right);
else if(current.left != null && current.right != null)
return nodes(current.left) + nodes(current.right);
} else return 1;
return 0;
}
The main method calls nodes like so:
System.out.println ("\nThis section finds the number of nodes "
+ "in the tree");
System.out.println ("The BST has " + bst.nodes() + " nodes");
So I was running the search by traveling in order, once I'd get to a node with no children I would delete the current node and return to the parent node and continue. I ran a debug of the method I have above and the program crashes with a NullPointerException() when it finally counts and removes all the nodes on the left and right side of the root node and tries to return 1.
This is for my lab, the method MUST be recursive.
I'm very lost at this point, does anyone know what I'm doing wrong?
You are making this way too complicated. The basic idea of object oriented programming is that you trust objects to do the jobs they know the answers to. So if I'm a parent, I can count myself, and I let my children count themselves, and so forth.
private int nodes(Entry<E> current) {
// if it's null, it doesn't exist, return 0
if (current == null) return 0;
// count myself + my left child + my right child
return 1 + nodes(current.left) + nodes(current.right);
}
You have several issues:
You're deleting nodes as you count them? Is nodes() supposed to clear the tree?
You're treating root==null, root!=null&left==null&&right==null, root!=null&left!=null&right==null, etc as separate cases. They're not. You have three cases, which are not entirely exclusive:
If the current node is not null, add one to the count. (This should always be the case. The only case where it might be false is if the current node == root, and we can detect and sidestep that beforehand.)
If the current node has a left child, add the left child's count.
If the current node has a right child, add the right child's count.
You're traversing back up the tree for some ungodly reason. Looks like it has something to do with deleting nodes...?
But the biggest thing in my opinion is, you're not giving enough autonomy to the Entrys. :P
A node can count its own children. Trust it to.
class Entry<E> {
...
int count() {
int result = 1;
if (left != null) result += left.count();
if (right != null) result += right.count();
return result;
}
}
public int nodes() {
return (root == null) ? 0 : root.count();
}
If your teacher is incompetent, and insists on some node-counting function outside a node, you can do the same thing you were trying to do:
private int nodes(Entry<E> current) {
int result = 1;
if (current.left) result += nodes(current.left);
if (current.right) result += nodes(current.right);
return result;
}
public int nodes() {
return (root == null) ? 0 : nodes(root);
}
But that teacher should be fired, in my opinion. The Entry class is the real tree; BinarySearchTree is really just a container for a reference to the root.
Also notice, i don't give a damn about the parents. If we start counting from the root, and each node counts its children, which count their children, etc etc... then all nodes will be accounted for.
public int countNodes(Node root){
// empty trees always have zero nodes
if( root == null ){
return 0;
}
// a node with no leafes has exactly one node
// note from editor: this pice of code is a micro optimization
// and not necessary for the function to work correctly!
if( root.left == null && root.right == null ){
return 1;
}
// all other nodes count the nodes from their left and right subtree
// as well as themselves
return countNodes( root.left ) + countNodes( root.right ) + 1;
}
After you delete current in: deleteEntry(current);, you use current.parent in return 1 + nodes(current.parent);
May be this's the reason of throwing NullPointerException..
Hey I have a very clean counting implemented for a binary tree:
public class Binary<T> where T: IComparable<T>
{
private Node _root;
public int Count => _root.Count;
public void Insert(T item)
{
Node newNode = new Node(item);
if (_root == null)
_root = newNode;
else
{
Node prevNode = _root;
Node treeNode = _root;
while (treeNode != null)
{
prevNode = treeNode;
treeNode = newNode.Item.CompareTo(treeNode.Item) < 1 ? treeNode.Left : treeNode.Right;
}
newNode.Parent = prevNode;
if (newNode.Item.CompareTo(prevNode.Item) < 1)
prevNode.Left = newNode;
else
prevNode.Right = newNode;
}
}
public class Node
{
public T Item;
public Node Parent;
public Node Left;
public Node Right;
public Node(T item, Node parent = null, Node left = null, Node right = null)
{
Item = item;
Parent = parent;
Left = left;
Right = right;
}
public int Count
{
get
{
int count = 1;
count += Left?.Count ?? 0;
count += Right?.Count ?? 0;
return count;
}
}
}
}
Maybe this helps you to understand how to implement a class for a simple binary tree with a count.
This implementation accesses the count through a count in the corresponding node in the tree.
Let me now if you are not familiar with the markup of .NET 4.6
I am pretty new to trees, and I am trying to create kind of a "leaf iterator". I'm thinking it should put all nodes that does not have a .left and .right value onto a stack, but I'm not sure how or even if it's the right thing to do. I have tried searching for it, but every example I come over starts with going to the leftmost leaf, and going p = node.parent, and I am avoiding linking to the node's parent.
I don't understand how I can repeatedlty start from the root and go through the vines without visiting the same vines over and over.
EDIT
I see people suggests using a recursive method to solve this, and I agree now. But I have been banging my head trying to find the solution for an iterator-class-way to do this for a while, and I still would like to know if that's possible, and how!
Use recursion:
public void visitNode(Node node) {
if(node.left != null) {
visitNode(node.left);
}
if(node.right != null) {
visitNode(node.right);
}
if(node.left == null && node.right == null) {
//OMG! leaf!
}
}
start it by supplying root:
visitNode(root);
In order to translate this into an Iterator<Node> you'll have to translate recursion to loop and then to traversal with state. Non-trivial, but should give you a lot of fun.
class Node {
public Node left = null;
public Node right = null;
// data and other goodies
}
class Tree {
public Node root = null;
// add and remove methods, etc.
public void visitAllLeaves(Node root) {
// visit all leaves starting at the root
java.util.Stack<Node> stack = new java.util.Stack<Node>();
if (root == null) return; // check to make sure we're given a good node
stack.push(root);
while (!stack.empty()) {
root = stack.pop();
if (root.left == null && root.right == null) {
// this is a leaf
// do stuff here
}
if (root.left != null) {
stack.push(root.left);
}
if (root.right != null) {
stack.push(root.right);
}
}
}
}
I'm not sure if the above code works, but that's somewhere along the lines of what needs to be done. Another option is javax.swing.TreeModel (half-joking).
Here is how one could implement an Iterator that would only return the leaf nodes, i.e. nodes without a left or right subtree.
The iterator searches for leaf nodes in the tree by doing a depth-first search, remembering the current state of the search in a stack and "pausing" when it has found a leaf node (see fetchNext() method).
The search is resumed when the client "consumes" the leaf node by calling next().
class Node {
public Node left;
public Node right;
}
class LeaveIterator implements Iterator<Node> {
private final Stack<Node> stack = new Stack<>();
private Node nextNode = null;
public LeaveIterator(Node root) {
if (root != null) {
stack.push(root);
nextNode = fetchNext();
}
}
private void fetchNext() {
Node next = null;
while (!stack.isEmpty() && next == null) {
Node node = stack.pop();
if (node.left == null && node.right == null) {
next = node;
}
if (node.right != null) {
stack.push(node.right);
}
if (node.left != null) {
stack.push(node.left);
}
}
return next;
}
public boolean hasNext() {
return nextNode != null;
}
public Node next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
Node n = nextNode;
nextNode = fetchNext();
return n;
}
public void remove() {
throw new UnsupportedOperationException();
}
}