BST - counting nodes with left and right children - java

As stated in the title, I'm trying to solve this problem by only counting nodes in a BST that have both left and right children. I'm struggling to think of the logic to solve this.
I thought of something like this.
First, check if the root is null or if it has any null children. Next, traverse the tree going right and continue to check the children, increment a counter when the conditions are met. But what happens when I reach the end node and need to go back to a node that had a left child to traverse? I had a temp node to keep track of the most previous parent, but what about when I need to go up more than one level? I'm assuming the answer to this problem is to recursively solve it, but I don't even know where to begin.
Here's what I have:
public int fullNodes() {
int count = 0;
Node n = root;
Node temp = null;
if (n == null || n.left == null && n.right == null) return count;
count++; //increment count, since the root has children on both sides
temp = n; //hold the previous place
n = n.right; //go right
//Now what?
return count;
}
I'm still struggling to think recursively when problem solving, in addition to my question, how do you learn to think recursively? Just a ton of practice, or is there some tricks and tips that you use to solve problems?

Rather than using a temp variable to hold the previous node -- which would only work for a depth of 1 -- call the same function on the child nodes.
Recursive tree traversal might look something like this:
public int countSomething (Node node) {
// Self;
//
int result = 1; // use your required logic here
// Children;
//
if (node.left != null)
result += countSomething( node.left);
if (node.right != null)
result += countSomething( node.right);
// done.
return result;
}
// example usages
int treeTotal = countSomething( rootNode);
int subtreeTotal = countSomething( subtree);
The execution callstack will then hold recursive invocations of the function, each with their appropriate context. When the top-level call returns, it will have summed the answer for the entire tree/ or subtree it was called on.
Put appropriate logic for your BST "node has both left & right children" in, instead of the constant 1.

First let us create representation of your Node class
class Node {
public Node left;
public Node right;
public Node(){}
public Node(Node left, Node right) {
this.left = left;
this.right = right;
}
}
Then we write our recusrive function and client that uses your function
public class Main {
public static int countNodes(Node root) {
if(root!=null && root.left!=null && root.right!=null) {
return 1+countNodes(root.left)+countNodes(root.right);
}
return 0;
}
public static void main(String[] args) {
Node right = new Node();
Node left = new Node();
Node root = new Node(left, right);
root.right = new Node(new Node(), new Node());
System.out.println(countNodes(root));
}
}

Related

Could someone please explain how recursion functionality is working on working tree data structure

While I am working in the below code, I didn't understand how recursion is working, because insertLevelOrder() function after completing root.left functionality cursor is coming outside, but how root.right functionality invoking again.
As per the logic after incrementing 'i' value, in the middle again 'i' is becoming zero.
It is so much of confusing, please help me some one to understand, Thanks in advance.
// Java program to construct binary tree from
// given array in level order fashion
public class ConstructTree {
Node root;
// Tree Node
static class Node {
int data;
Node left, right;
Node(int data)
{
this.data = data;
this.left = null;
this.right = null;
}
}
// Function to insert nodes in level order
public Node insertLevelOrder(int[] arr, Node root,
int i)
{
// Base case for recursion
if (i < arr.length) {
Node temp = new Node(arr[i]);
root = temp;
// insert left child
root.left = insertLevelOrder(arr, root.left,
2 * i + 1);
// insert right child
root.right = insertLevelOrder(arr, root.right,
2 * i + 2);
}
return root;
}
// Function to print tree nodes in InOrder fashion
public void inOrder(Node root)
{
if (root != null) {
inOrder(root.left);
System.out.print(root.data + " ");
inOrder(root.right);
}
}
// Driver program to test above function
public static void main(String args[])
{
ConstructTree t2 = new ConstructTree();
int arr[] = { 6, 6};
t2.root = t2.insertLevelOrder(arr, t2.root, 0);
t2.inOrder(t2.root);
}
}

debugging custom binary tree specific the total(maximum) depth method

As for my question: I have a Node class:
public class Node<E> {
private E value;
private Node<E> left;
private Node<E> right;
public Node(E value) {
this.value = value;
this.left = null;
this.right = null;
}
and this class has two methods which calculate the depth of the node (binary tree). The method totaldepth() I wrote myself and it gives an incorrect answer, for which I need your help debugging. The method maxDepth(Node node) gives the correct answer and was used as reference material by me. Could you help me debug totalDepth method as to me it looks the same as maxDepthby the result.
incorrect code:
public int totalDepth() {
// initialize variabele depth
int depth = 0;
// reached leaf return 0
if (right == null && left == null) {
return 0;
}
// not yet reached leaf, continue deeper
else {
int leftdepth = 0;
int rightdepth = 0;
// left node is not null continue going left
if (left != null) {
leftdepth = left.totalDepth();
}
// right node is not null continue going right
if (right != null) {
rightdepth = right.totalDepth();
}
if (leftdepth > rightdepth) {
// 1 is needed because each call to totalDepth raises depth by 1
depth = leftdepth + 1;
}
else {
depth = rightdepth + 1;
}
}
return depth;
}
correct code:
public int maxDepth(Node node) {
if (node == null) {
return (0);
}
else {
// compute the depth of each subtree
int leftDepth = maxDepth(node.left);
int rightDepth = maxDepth(node.right);
// use the larger one
if (leftDepth > rightDepth)
return (leftDepth + 1);
else
return (rightDepth + 1);
}
}
Also I'm just starting to learn how to code so forgive me for all the inefficient things I'm doing. Thanks in advance for helping me!
Your totalDepth method will not work, because you have a tree, and you don't actually know, how many elements you have from the left and the right. Balanced this tree or not. So, only way to walk throw the tree, is to use Breadth-first search or Depth-first search algorithm, and they are based of recursion function like maxDepth(Node node) method.

Java: Binary Search Tree

I decided to create a Binary Search Tree using java, and what I want to do is delete the Max element from the tree, so I created this part of code:
public Node<T> removeMax(Node<T> node) {
if (node == null)
return null;
if (node.right == null) {
Node<T> n = node;
node = null;
return n;
}
return removeMax(node.right);
}
The method returns the Max element, but it doesn't remove it from the tree. As you can see, I tried to remove it in this part:
Node<T> n = node;
node = null;
return n;
But, when I print the elements in the tree, it shows the "removed" ones too.
What am I doing wrong?
EDIT: What I'm really trying to do is delete the Max node and return it so I can now which one was deleted.
Now I noticed you wanted to know which node gets deleted. All you can do is to delete the maximum node and print the tree:
public void deleteMax(Node<T> root) {
Node<T> current = root;
while (current.right.right != null) {
current = current.right;
}
if(current.right.left!=null) {//max has 1 child to left
current.right=current.right.left;
}
else {//max has no child
current.right=null;
}
}
public String printInfix(Node<T> root) {//prints all the data in the tree in infix order
if(root==null) {
return "";
}
return printAll(root.left+" "+root.data+" "+printAll(root.right);
}
You want to delete a node in a binary search tree. So, basically what you want to do is to make it inaccessible. To do that, you have to nullify the reference to it, i.e, make its parent's corresponding pointer to it as null.
Change this:
if (node.right == null) {
Node<T> n = node;
node = null;
return n;
}
To this:
if (node.right.right == null) {
Node<T> n = node.right;
node.right = node.right.left;
return n;
}
Also you need to take care of the case when the root is the maximum element of the tree. So, if you have some reference to the root of BST, add this case before the above case:
if (node.right == null) {
Node<T> n = node;
referenceToTheRootOfBST = node.left;
return n;
}
If you don't have a reference to the root of the BST, what you can do is deep copy the left node of the root and then remove the left node. So, the above case changes to:
if (node.right == null) {
Node<T> n = node;
//I'll assume you don't call this function if root is the only element.
//if root is the only element.If that's the case, then just make the
//root null before calling this function.
Node<T> leftNode = node.left;
node.value = leftNode.value;
node.left = leftNode.left;
node.right = leftNode.right;
return n;
}
Another simple way to handle the case that root is the maximum element is to check it before actually calling this function. Simply check if root has a right node, and if it doesn't have it, reallocate the root reference.

Recursively count the number of leaves in a binary tree without given parameters

I am struggling to figure out how to code a recursive algorithm to count the number of leaves in a Binary Tree (not a complete tree). I get as far as traversing to the far most left leaf and don't know what to return from there. I am trying to get the count by loading the leaves into a list and getting the size of that list. This is probably a bad way to go about the count.
public int countLeaves ( ) {
List< Node<E> > leafList = new ArrayList< Node<E> >();
//BinaryTree<Node<E>> treeList = new BinaryTree(root);
if(root.left != null)
{
root = root.left;
countLeaves();
}
if(root.right != null)
{
root = root.right;
countLeaves();
}
if(root.left == null && root.right == null)
{
leafList.add(root);
}
return();
}
Elaborating on #dasblinkenlight idea. You want to recursively call a countleaves on root node & pass back the # to caller. Something on the following lines.
public int countLeaves() {
return countLeaves(root);
}
/**
* Recursively count all nodes
*/
private static int countLeaves (Node<E> node) {
if(node==null)
return 0;
if(node.left ==null && node.right == null)
return 1;
else {
return countLeaves(node.left) + countLeaves(node.right);
}
}
Edit: It appears, a similar problem was previously asked counting number of leaf nodes in binary tree
The problem with your implementation is that it does not restore the value of member variable root back to the state that it had prior to entering the method. You could do it by storing the value in a local variable, i.e.
Node<E> oldRoot = root;
... // your method goes here
root = oldRoot;
However, a better approach is to take Node<E> as an argument, rather than relying on a shared variable:
public int countLeaves() {
return countLeaves(root);
}
private static int countLeaves (Node<E> node) {
... // Do counting here
}

Adding elements to cyclic Single Linked Lists

I am trying to add an element to the end of a cyclic Single Linked List for my homework
assignment. But for some reason I am having a lot of problems.
I have a _tail pointer, and _dummy. The add method in JUnit test says that when checking the add method it returns null instead of 1. (1 being what was added to list)
Here is my code
private static class Node<T>{
Node<T> next;
T data;
public Node(T data, Node<T> next){
this.next = next;
this.data = data;
}
}
private Node<T> _tail;
private int _count;
private int _version;
private Node<T> _dummy;
public CyclicLinkedList(){
_dummy = new Node<T>(null, null);
_dummy.next = _dummy;
_tail = _dummy;
_count = 0;
assert _wellFormed();
}
and here is my add method
#Override
public boolean add(T x){
assert _wellFormed();
Node<T> n = new Node<T>(x, _tail.next);
_tail.next = n;
_tail = n;
++_version;
++_count;
assert _wellFormed();
return true;
}
The assertWellformed states that the linked list is wrongly cyclic. The _wellFormed() method has already been implemented by the class instructor so that is not the problem. Need some pointers! Thanks. Here is the test to see if the test is wrongly cyclic.
// check for cycles:
Node<T> fast = _tail.next;
for (Node<T> p = _tail; fast != null && fast.next != null && fast != _tail && fast.next != _tail; p = p.next) {
if (p == fast) return _report("list is wrongly cyclic");
fast = fast.next.next;
}
_tail.next = n;
_tail = n;
You should add one more line at the start of that code in add method:-
n.next = _tail.next;
So, your code becomes: -
n.next = _tail.next;
_tail.next = n;
_tail = n;
You need to make your new node point to the first node, to make it cyclic.
And since, _tail.next I assume must be pointing to the first element, before adding a new node to the List, so assign _tail.next to n.next before adding it to the list to make n also now point to the first node.
So, at the first line, both your nodes: - n node and _tail node, point to the first node. Now, detach your _tail node from first node, and make it point to the n node. And at last, make your n node as _tail node.

Categories