Getting nth item of a BST - java

I am trying to return the data held by the nth item of a BST, I'm trying to do an inorder traversal with a counter, and when the counter is larger than n, return the current node. My current code seems to always return the first item, and I can't see where my logic is wrong. I only wrote the nth and inOrder methods, the rest were provided. I think I'm incrementing my counter too often, is that the cause or am I doing something else wrong. I'll post the main method I'm testing with below as well.
import java.util.NoSuchElementException;
public class BST {
private BTNode<Integer> root;
public BST() {
root = null;
}
public boolean insert(Integer i) {
BTNode<Integer> parent = root, child = root;
boolean goneLeft = false;
while (child != null && i.compareTo(child.data) != 0) {
parent = child;
if (i.compareTo(child.data) < 0) {
child = child.left;
goneLeft = true;
} else {
child = child.right;
goneLeft = false;
}
}
if (child != null)
return false; // number already present
else {
BTNode<Integer> leaf = new BTNode<Integer>(i);
if (parent == null) // tree was empty
root = leaf;
else if (goneLeft)
parent.left = leaf;
else
parent.right = leaf;
return true;
}
}
public int greater(int n) {
if (root == null) {
return 0;
}
else {
return n;
}
}
int c = 0;
public int nth(int n) throws NoSuchElementException {
BTNode<Integer> node = null;
if (root == null) {
throw new NoSuchElementException("Element " + n + " not found in tree");
}
else {
if (root != null){
node = inOrder(root, n);
}
}
return node.data;
}
public BTNode inOrder(BTNode<Integer> node, int n) {
c++;
while (c <= n) {
if (node.left != null) {
inOrder(node.left, n);
}
c++;
if (node.right != null) {
inOrder(node.right, n);
}
}
return node;
}
}
class BTNode<T> {
T data;
BTNode<T> left, right;
BTNode(T o) {
data = o;
left = right = null;
}
}
public class bstTest {
public static void main(String[] args) {
BST tree = new BST();
tree.insert(2);
tree.insert(5);
tree.insert(7);
tree.insert(4);
System.out.println(tree.nth(2));
}
}

An invariant you should consider is that when n = sizeOfLeftSubtree + 1, then return that node. If n is less, then go left. If n is greater, then go right and reduce n by sizeOfLeftSubtree+1. Note that I map n=1 to the first element (the leftmost element).
You could trivially calculate the size of a subtree recursively, or you can store the size at every root (every node is a root of a subtree) modifying you insert method (save in a stack/queue all nodes visited and if a new node is added just increment all sizes by 1).
If the size is stored the complexity will be O(log n). If not if could become O(n^2).
public int nth(int n) throws NoSuchElementException {
if( sizeOfTree(this.root) < n || n < 1)
throw new NoSuchElementException("Element " + n + " not found in tree");
BTNode<Integer> root = this.root;
boolean found = false;
do{
int sizeOfLeftSubtree = sizeOfTree(root.left);
if( sizeOfLeftSubtree + 1 == n ){
found = true;
}else if( n < sizeOfLeftSubtree+1 ){
root = root.left;
}else if( sizeOfLeftSubtree+1 < n ){
root = root.right;
n -= sizeOfLeftSubtree+1;
}
}while( !found );
return root.data;
}
public int sizeOfTree(BTNode<Integer> root){
if( root == null )
return 0;
else
return sizeOfTree(root.left) + 1 + sizeOfTree(root.right);
}

You don't change node in the inOrder method.
public BTNode inOrder(BTNode<Integer> node, int n) {
c++;
while (c <= n) {
if (node.left != null) {
// **** Add this - or something.
node = inOrder(node.left, n);
}
c++;
if (node.right != null) {
// **** Add this - or something.
node = inOrder(node.right, n);
}
}
return node;
}
Not suggesting this is the bug you are trying to fix but it is certainly a problem with the code.

Related

writing a proper binary tree height function?

I'm trying to write a function that displays the height of my binary search tree which is displayed below. The problem is I'm supposed to write a function that doesn't have any arguments or parameters. This is really stumping me. I tried declaring root outside the parameter list but that didn't work. Any solutions?
int height (Node root){
if (root == null) {
return 0;
}
int hleftsub = height(root.m_left);
int hrightsub = height(root.m_right);
return Math.max(hleftsub, hrightsub) + 1;
}
the method signature provide by my instructor is
int height ()
EDIT:
my full code
import javax.swing.tree.TreeNode;
import java.util.Scanner;
import java.io.FileNotFoundException;
import java.io.File;
import java.util.ArrayList;
class BinarySearchTree<E extends Comparable<E>> {
public Node<E> root;
public int m_size = 0;
public BinarySearchTree() {
}
public boolean search(E value) {
boolean ret = false;
Node<E> current = root;
while (current != null && ret != true) {
if (current.m_value.compareTo(current.m_value) == 0) {
ret = true;
} else if (current.m_value.compareTo(current.m_value) > 0) {
current = current.m_left;
} else {
current = current.m_right;
}
}
return false;
}
public boolean insert(E value) {
if (root == null) {
root = new Node<>(value);
m_size++;
} else {
Node<E> current = root;
Node<E> parentNode = null;
while (current != null)
if (current.m_value.compareTo(value) > 0) {
parentNode = current;
current = current.m_left;
} else if (current.m_value.compareTo(value) < 0) {
parentNode = current;
current = current.m_right;
} else {
return false;
}
if (current.m_value.compareTo(value) < 0) {
parentNode.m_left = new Node<>(value);
} else {
parentNode.m_right = new Node<>(value);
}
}
m_size++;
return true;
}
boolean remove(E value) {
if (!search(value)) {
return false;
}
Node check = root;
Node parent = null;
boolean found = false;
while (!found && check != null) {
if (value.compareTo((E) check.m_value) == 0) {
found = true;
} else if (value.compareTo((E) check.m_value) < 0) {
parent = check;
check = check.m_left;
} else {
parent = check;
check = check.m_right;
}
}
if (check == null) {
return false;
} else if (check.m_left == null) {
if (parent == null) {
root = check.m_right;
} else if (value.compareTo((E) parent.m_value) < 0) {
parent.m_left = check.m_right;
} else {
parent.m_right = check.m_right;
}
} else {
Node<E> parentofRight = check;
Node<E> rightMost = check.m_left;
while (rightMost.m_right != null) {
parentofRight = rightMost;
rightMost = rightMost.m_right;
}
check.m_value = rightMost.m_value;
if (parentofRight.m_right == rightMost) {
rightMost = rightMost.m_left;
} else {
parentofRight.m_left = rightMost.m_left;
}
}
m_size--;
return true;
}
int numberNodes () {
return m_size;
}
int height (Node root){
if (root == null) {
return 0;
}
int hleftsub = height(root.m_left);
int hrightsub = height(root.m_right);
return Math.max(hleftsub, hrightsub) + 1;
}
int numberLeafNodes(Node node){
if (node == null) {
return 0;
}
else if(node.m_left == null && node.m_right == null){
return 1;
}
else{
return numberLeafNodes(node.m_left) + numberLeafNodes(node.m_right);
}
}
void display(String message){
if(root == null){
return;
}
display(String.valueOf(root.m_left));
display(String.valueOf(root));
display(String.valueOf(root.m_right));
}
}
class Node<E> {
public E m_value;
public Node<E> m_left;
public Node<E> m_right;
public Node(E value) {
m_value = value;
}
}
If you traverse the tree iteratively, you can get the height without recursion. Anything recursive can be implemented iteratively. It may be more lines of code though. This would be a variation of level order graph / tree traversal.
See: https://www.geeksforgeeks.org/iterative-method-to-find-height-of-binary-tree/
If you use that implementation, delete the parameter, as height() will already have access to root.
This however requires a queue and is O(n) time and O(n) space.
height() may be a public method that calls a private method height(Node node) that starts recursion. O(n) time, O(1) space for BST.
You can pass height as an extra parameter where recursively inserting into the tree so that you are counting the number of recursive calls (which is directly correlated with the depth / # of levels down in the tree you are). Once a node finds it's place, if the height (# of recursive calls) you were passing exceeds the instance variable height stored by the tree, you update the instance variable to the new height. This will also allow tree.height() to be a constant time function. O(1) time, O(1) space.

Counting the number of nodes in Leaf diagram

Been working on this for while with no luck. Hopefully someone can point in the right direction.
Code:
public class BST {
public BTNode<Integer> root;
int nonLeafCount = 0;
int depthCount = 0;
public BST() {
root = null;
}
class BTNode<T> {
T data;
BTNode<T> left, right;
BTNode(T o) {
data = o;
left = right = null;
}
public String toString() {
return String.valueOf(data);
}
}
}
The easy way to traverse a tree without recursive calls is to use a stack. Push the root on the stack, then enter a loop that - so long as the stack is not empty - pops a node from the stack and pushes the non-null children of that node. It's pretty obvious that this will eventually push every node onto the stack exactly once and pop it exactly once. Now all you need to do is count the popped nodes that have at least one child. Putting this together,
public int nonleaves() {
int nonLeafCount = 0;
BTNode<Integer> [] stack = new BTNode[2];
int p = 0;
stack[p++] = root; // push root
while (p != 0) {
BTNode<Integer> node = stack[--p]; // pop
if (node.left != null || node.right != null) ++nonLeafCount;
if (p + 1 >= stack.length) stack = Arrays.copyOf(stack, 2 * stack.length);
if (node.right != null) stack[p++] = node.right; // push right
if (node.left != null) stack[p++] = node.left; // push left
}
return nonLeafCount;
}
Note that in accordance with your description, I used a simple Java array for a stack, growing it by a factor of 2 whenever it fills up. Integer p is the stack pointer.
Also, this code assumes the root is non-null. If the root can be null, add a check at the start and return 0 in that case.
NB it's possible to traverse without even a stack by several methods, although at the cost of changing the tree during traversal. (It's back in its original shape when the traversal is complete.) The nicest IMO is Morris's algorithm, but all of them are considerably more complicated than the stack. Since it seems you're a new programmer, figure out the stack method first.
Edit
To find max depth:
public int maxDepth() {
int max = 0;
Pair<Integer> [] stack = new Pair[2];
int p = 0;
stack[p++] = new Pair(root, 1);
while (p != 0) {
Pair<Integer> pair = stack[--p];
if (pair.depth > max) max = pair.depth;
if (p + 1 >= stack.length) stack = Arrays.copyOf(stack, 2 * stack.length);
if (pair.node.right != null)
stack[p++] = new Pair(pair.node.right, 1 + pair.depth);
if (pair.node.left != null)
stack[p++] = new Pair(pair.node.left, 1 + pair.depth);
}
return max;
}
private static class Pair<T> {
BTNode<T> node;
int depth;
Pair(BTNode<T> node, int depth) {
this.node = node;
this.depth = depth;
}
}
Finally, I'd be remiss if I didn't point out that we can do some algebra on the algorithm to eliminate some tiny inefficiencies. You'll note that after the left child is pushed onto the stack, it is certain to be popped in the next loop iteration. The root push/pop is similar. We might as well set node directly. Also, there are some redundant comparisons. The details are too much for this note, but here is a reworked non-leaf counter (untested but ought to work fine):
public int nonleaves() {
int nonLeafCount = 0;
BTNode<Integer>[] stack = new BTNode[1];
int p = 0;
BTNode<Integer> node = root;
for (;;) {
if (node.left == null) {
if (node.right == null) {
if (p == 0) break;
node = stack[--p];
} else { // node.right != null
++nonLeafCount;
node = node.right;
}
} else { // node.left != null
++nonLeafCount;
if (node.right != null) {
if (p >= stack.length) {
stack = Arrays.copyOf(stack, 2 * stack.length);
}
stack[p++] = node.right;
}
node = node.left;
}
}
return nonLeafCount;
}
You can see that to eek out a tiny bit of efficiency we lose a lot of simplicity. This is almost always a bad bargain. I recommend against it.
A possible solution:
public class BST<T> {
public BTNode<T> root;
int depthCount = 0;
public BST() {
root = null;
}
public int nonleaves() { // Method must be declared like this. No
// parameters.
BTNode<T> current = root;
BTNode<T> previous = null;
int nonLeafCount = 0;
while (current != null) {
if (previous == current.parent) { // this includes when parent is
// null, i.e. current is the
// root.
previous = current;
if (current.left != null) {
nonLeafCount++;
current = current.left;
} else if (current.right != null) {
nonLeafCount++;
current = current.right;
} else {
current = current.parent;
}
} else if (previous == current.left) {
previous = current;
if (current.right != null) {
current = current.right;
} else {
current = current.parent;
}
} else {
// previous==current.right
previous = current;
current = current.parent;
}
}
return nonLeafCount;
}
private static class BTNode<T> {
BTNode<T> left, right, parent;
/* ... */
}
}
Using stacks:
public class BST2<T> {
public BTNode<T> root;
int depthCount = 0;
public BST2() {
root = null;
}
public int nonleaves() { // Method must be declared like this. No
// parameters.
BTNode<T> current = root;
BTNode<T> previous = null;
int nonLeafCount = 0;
MyStack myStack = new MyStack(); // New empty stack
while (current != null) {
if (previous == myStack.top()) { // this includes when stack is
// empty, i.e. current is the
// root.
myStack.push(current);
previous = current;
if (current.left != null) {
nonLeafCount++;
current = current.left;
} else if (current.right != null) {
nonLeafCount++;
current = current.right;
} else {
myStack.pop();
current = myStack.top();
}
} else if (previous == current.left) {
previous = current;
if (current.right != null) {
current = current.right;
} else {
myStack.pop();
current = myStack.top();
}
} else {
// previous==current.right
previous = current;
myStack.pop();
current = myStack.top();
}
}
return nonLeafCount;
}
private static class BTNode<T> {
BTNode<T> left, right;
/* ... */
}
}

How to print integers in ascending order from a balanced binary search tree?

This a program creates balanced binary search tree from an array integer and later on, prints the value in-order ( X.left, X, X.right). Any suggestion for improving the program appreciated.
It would be good to note, there are several other ways for traversing a BST. Such as -
Pre-order : X, X.left, X.right
Post-order : X.left, X.right, X
Note # I eventually solved the issue with some help from the user of this program. It needed to change some conditions inside the createMinimalBST method.
// we need to stop recursion there as one element exist
if (start == mid-1) {
}
// we need to stop recursion there as one element exist
if (end == mid+1) {
}
THANK YOU.
// import java.util.Arrays;
// import java.util.LinkedList;
import java.util.*;
class Node {
int key;
Node leftChild;
Node rightChild;
Node(int key) {
this.key = key;
}
Node() {
// null constructor
}
public String toString() {
return "\n"+key+" ";
}
}
public class BinaryTree {
Node root;
static int TWO_NODES_FOUND = 2;
static int ONE_NODE_FOUND = 1;
static int NO_NODES_FOUND = 0;
BinaryTree (){
root = null;
}
public void addNode(int key) {
Node newNode = new Node(key);
// If there is no root this becomes root
if (root == null) {
root = newNode;
}
else {
// Set root as the Node we will start
// with as we traverse the tree
Node focusNode = root;
Node parent;
while (true) {
parent = focusNode;
if (key < focusNode.key) {
focusNode = focusNode.leftChild;
if (focusNode == null) {
parent.leftChild = newNode;
return; // All Done
}
} // end of if
else {
focusNode = focusNode.rightChild;
if (focusNode == null) {
parent.rightChild = newNode;
return;
}
}
}
}
}
// get the height of binary tree
public int height(Node root) {
if (root == null)
return -1;
Node focusNode = root;
int leftHeight = focusNode.leftChild != null ? height( focusNode.leftChild) : 0;
int rightHeight = focusNode.rightChild != null ? height( focusNode.rightChild) : 0;
return 1 + Math.max(leftHeight, rightHeight);
}
// METHODS FOR THE TREE TRAVERSAL
// inOrderTraverseTree : i) X.left ii) X iii) X.right
public void inOrderTraverseTree(Node focusNode) {
if (focusNode != null) {
inOrderTraverseTree(focusNode.leftChild);
// System.out.println(focusNode);
System.out.print( focusNode );
inOrderTraverseTree(focusNode.rightChild);
}
// System.out.println();
}
// preOrderTraverseTree : i) X ii) X.left iii) X.right
public void preorderTraverseTree(Node focusNode) {
if (focusNode != null) {
System.out.println(focusNode);
preorderTraverseTree(focusNode.leftChild);
preorderTraverseTree(focusNode.rightChild);
}
}
// postOrderTraverseTree : i) X.left ii) X.right iii) X
public void postOrderTraverseTree(Node focusNode) {
if (focusNode != null) {
preorderTraverseTree(focusNode.leftChild);
preorderTraverseTree(focusNode.rightChild);
System.out.println(focusNode);
}
}
// get certain node from it's key
public Node findNode(int key) {
Node focusNode = root;
while (focusNode.key != key) {
if (key < focusNode.key) {
focusNode = focusNode.leftChild;
} else {
focusNode = focusNode.rightChild;
}
if (focusNode == null)
return null;
}
return focusNode;
}
public boolean remove(int key) {
Node focusNode = root;
Node parent = root;
boolean isItALeftChild = true;
// we will remove the focusNode
while (focusNode.key != key) {
parent = focusNode;
if (key < focusNode.key) {
isItALeftChild = true;
focusNode = focusNode.leftChild;
}
else {
isItALeftChild = false;
focusNode = focusNode.rightChild;
}
if (focusNode == null)
return false;
}
// no child
if (focusNode.leftChild == null && focusNode.rightChild == null) {
if (focusNode == root)
root = null;
else if (isItALeftChild)
parent.leftChild = null;
else
parent.rightChild = null;
}
// one child ( left child )
else if (focusNode.rightChild == null) {
if (focusNode == root)
root = focusNode.leftChild;
else if (isItALeftChild)
parent.leftChild = focusNode.leftChild;
else
parent.rightChild = focusNode.leftChild;
}
else if (focusNode.leftChild == null) {
if (focusNode == root)
root = focusNode.rightChild;
else if (isItALeftChild)
parent.leftChild = focusNode.rightChild;
else
parent.rightChild = focusNode.rightChild;
}
// two children exits
else {
// replacement is the smallest node in the right subtree
// we neeed to delete the focusNode
Node replacement = getReplacementNode(focusNode);
if (focusNode == root)
root = replacement;
else if (isItALeftChild)
parent.leftChild = replacement;
else
parent.rightChild = replacement;
replacement.leftChild = focusNode.leftChild;
}
return true;
}
public Node getReplacementNode(Node replacedNode) {
Node replacementParent = replacedNode;
Node replacement = replacedNode;
Node focusNode = replacedNode.rightChild;
// find the smallest node of the right subtree of the node to be deleted
while (focusNode != null) {
replacementParent = replacement;
replacement = focusNode;
focusNode = focusNode.leftChild;
}
// exit when the focusNode is null
// the replacement is the smallest of the right subtree
if (replacement != replacedNode.rightChild) {
replacementParent.leftChild = replacement.rightChild;
replacement.rightChild = replacedNode.rightChild;
}
return replacement;
}
private void createMinimalBST(int arr[], int start, int end, Node newNode){
if ( end <= start ) return;
int mid = (start + end) / 2;
newNode.key = arr[mid];
// System.out.println("new node = "+ newNode );
if (start <= mid-1) {
if ( start < mid-1){
newNode.leftChild = new Node();
createMinimalBST( arr, start, mid - 1, newNode.leftChild );
}
else {
newNode.leftChild = new Node();
newNode.leftChild.key = arr[start];
}
}
if ( mid+1 <= end ) {
if ( mid+1 < end){
newNode.rightChild = new Node();
createMinimalBST(arr, mid + 1, end, newNode.rightChild);
}
else {
newNode.rightChild = new Node();
newNode.rightChild.key = arr[end];
}
}
// System.out.println("left child = "+ newNode.leftChild +" "+ " right child = "+ newNode.rightChild);
}
public static int getHeight(Node root) {
if (root == null) {
return 0;
}
return Math.max(getHeight(root.leftChild), getHeight(root.rightChild)) + 1;
}
public static boolean isBalanced( Node root) {
if (root == null) {
return true;
}
int heightDiff = getHeight(root.leftChild) - getHeight(root.rightChild);
if (Math.abs(heightDiff) > 1) {
return false;
}
else {
return isBalanced(root.leftChild ) && isBalanced(root.rightChild );
}
}
public void createMinimalBST(int array[]) {
// Node n = new Node();
Arrays.sort(array);
root = new Node();
createMinimalBST(array, 0, array.length - 1, root);
}
// create linked list of the same level of the tree
public static ArrayList<LinkedList<Node>> createLevelLinkedList( Node root) {
ArrayList<LinkedList<Node>> result = new ArrayList<LinkedList<Node>>();
/* "Visit" the root */
LinkedList<Node> current = new LinkedList<Node>();
if ( root != null) {
current.add(root);
}
while ( current.size() > 0) {
result.add(current); // Add previous level
LinkedList<Node> parents = current; // Go to next level
current = new LinkedList<Node>();
for ( Node parent : parents) {
/* Visit the children */
if (parent.leftChild != null) {
current.add(parent.leftChild);
}
if (parent.rightChild != null) {
current.add(parent.rightChild );
}
}
}
return result;
}
// print values in the same level of the tree gradually
public static void printResult(ArrayList<LinkedList<Node>> result){
int depth = 0;
for(LinkedList<Node> entry : result) {
Iterator<Node> i = entry.listIterator();
System.out.print("Link list at depth " + depth + ":");
while(i.hasNext()){
System.out.print(" " + ((Node)i.next()).key );
}
System.out.println();
depth++;
}
}
// using a key, check whether the node is inside of the BST or not
public boolean isBST (int n){
if ( n == root.key ){
return true;
}
else {
Node focusNode = root;
Node parent;
while( focusNode != null){
parent = focusNode;
if (focusNode != null){
if (n < focusNode.key){
focusNode = focusNode.leftChild;
}
else {
focusNode = focusNode.rightChild;
}
}
if ( focusNode != null && n == focusNode.key ){
return true;
}
}
}
return false;
}
//
public Node getNode (int n){
if ( n == root.key ){
return root;
}
else {
Node focusNode = root;
Node parent;
while( focusNode != null){
parent = focusNode;
if (focusNode != null){
if (n < focusNode.key){
focusNode = focusNode.leftChild;
}
else {
focusNode = focusNode.rightChild;
}
}
if ( focusNode != null && n == focusNode.key ){
return focusNode;
}
}
}
return null;
}
// get the parent of using the key of certain node
public Node getParent (int n){
if ( !isBST (n)){
return null;
}
if ( n == root.key ){
return null;
}
else {
Node focusNode = root;
Node parent;
while( focusNode != null){
parent = focusNode;
if (focusNode != null){
if (n < focusNode.key){
focusNode = focusNode.leftChild;
}
else {
focusNode = focusNode.rightChild;
}
}
if ( focusNode != null && n == focusNode.key ){
return parent;
}
}
}
return null;
}
/* get in-order successive node of the certain node */
public Node inorderSucc( Node n) {
if (n == null) return null;
// Found right children -> return left most node of right subtree
if ( getParent(n.key) == null || n.rightChild != null) {
return leftMostChild( n.rightChild );
}
else {
Node q = n;
Node x = getParent(q.key);
// Go up until we’re on left instead of right
while (x != null && x.leftChild != q) {
q = x;
x = getParent(x.key);
}
return x;
}
}
/* get the left most/ smallest node of the sub tree of the certain node */
public Node leftMostChild( Node n) {
if (n == null) {
return null;
}
while (n.leftChild != null) {
n = n.leftChild;
}
return n;
}
// SECOOND SOLUTION TO FIND OUT THE COMMON ANCESTOR OF TWO NODES
public static boolean covers2( Node root, Node p) {
if (root == null) return false;
if (root == p) return true;
return covers2(root.leftChild , p) || covers2(root.rightChild , p);
}
public static Node commonAncestorHelper( Node root, Node p, Node q) {
if (root == null) {
return null;
}
boolean is_p_on_left = covers2(root.leftChild , p);
boolean is_q_on_left = covers2(root.leftChild , q);
if (is_p_on_left != is_q_on_left) { // Nodes are on different side
return root;
}
// nodes are the same sides
Node child_side = is_p_on_left ? root.leftChild : root.rightChild;
return commonAncestorHelper(child_side, p, q);
}
public static Node commonAncestor2( Node root, Node p, Node q) {
if (!covers2(root, p) || !covers2(root, q)) { // Error check - one node is not in tree
return null;
}
return commonAncestorHelper(root, p, q);
}
// END OF THE SECOND SOLUTION
// FIRST SOLUTION TO FIND OUT THE COMMON ANCESTOR OF TWO NODES
// Checks how many “special” nodes are located under this root
public static int covers( Node root, Node p, Node q) {
int ret = NO_NODES_FOUND;
if (root == null) return ret;
if (root == p || root == q)
ret += 1;
ret += covers(root.leftChild , p, q);
if(ret == TWO_NODES_FOUND) // Found p and q
return ret;
return ret + covers(root.rightChild , p, q);
}
public static Node commonAncestor( Node root, Node p, Node q) {
if (q == p && (root.leftChild == q || root.rightChild == q))
return root;
int nodesFromLeft = covers(root.leftChild, p, q); // Check left side
if ( nodesFromLeft == TWO_NODES_FOUND ) {
if(root.leftChild == p || root.leftChild == q)
return root.leftChild;
else return commonAncestor(root.leftChild , p, q);
}
else if (nodesFromLeft == ONE_NODE_FOUND) {
if (root == p) return p;
else if (root == q) return q;
}
int nodesFromRight = covers(root.rightChild, p, q); // Check right side
if(nodesFromRight == TWO_NODES_FOUND) {
if(root.rightChild == p || root.rightChild == q)
return root.rightChild;
else return commonAncestor(root.rightChild , p, q);
}
else if (nodesFromRight == ONE_NODE_FOUND) {
if (root == p) return p;
else if (root == q) return q;
}
if (nodesFromLeft == ONE_NODE_FOUND &&
nodesFromRight == ONE_NODE_FOUND) return root;
else return null;
}
// END OF THE FIRST SOLUTION
// METHODS FOR SUBTREE CHECK
// Check if T2 is subtree of T1
public static boolean containsTree( Node t1, Node t2) {
if (t2 == null)
return true; // The empty tree is a subtree of every tree.
else
return subTree(t1, t2);
}
/* Checks if the binary tree rooted at r1 contains the binary tree
* rooted at r2 as a subtree somewhere within it.
*/
public static boolean subTree( Node r1, Node r2) {
if (r1 == null)
return false; // big tree empty & subtree still not found.
if (r1.key == r2.key) {
if (matchTree(r1,r2)) return true;
}
return (subTree(r1.leftChild , r2) || subTree(r1.rightChild , r2));
}
/*
Checks if the binary tree rooted at r1 contains the
binary tree rooted at r2 as a subtree starting at r1.
*/
public static boolean matchTree( Node r1, Node r2) {
if (r2 == null && r1 == null)
return true; // nothing left in the subtree
if (r1 == null || r2 == null)
return false; // big tree empty & subtree still not found
if (r1.key != r2.key)
return false; // data doesn’t match
return (matchTree(r1.leftChild, r2.leftChild) &&
matchTree(r1.rightChild , r2.rightChild ));
}
// END OF SUBTREE CHECK
/* Creates tree by mapping the array left to right, top to bottom. */
public Node createTreeFromArray(int[] array) {
if (array.length > 0) {
root = new Node(array[0]);
java.util.Queue<Node> queue = new java.util.LinkedList<Node>();
queue.add(root);
boolean done = false;
int i = 1;
while (!done) {
Node r = (Node) queue.element();
if (r.leftChild == null) {
r.leftChild = new Node(array[i]);
i++;
queue.add(r.leftChild);
}
else if (r.rightChild == null) {
r.rightChild = new Node(array[i]);
i++;
queue.add(r.rightChild );
}
else {
queue.remove();
}
if (i == array.length)
done = true;
}
return root;
}
else {
return null;
}
}
// ALGORITHM TO FIND ALL THE PATHS TO CERTAIN SUM VALUE
public static void findSum( Node node, int sum, int[] path, int level) {
if (node == null) {
return;
}
/* Insert current node into path */
path[level] = node.key;
int t = 0;
for (int i = level; i >= 0; i--){
t += path[i];
if (t == sum) {
print(path, i, level);
}
}
findSum( node.leftChild, sum, path, level + 1);
findSum( node.rightChild , sum, path, level + 1);
/* Remove current node from path. Not strictly necessary, since we would
* ignore this value, but it's good practice.
*/
path[level] = Integer.MIN_VALUE;
}
public static int depth( Node node) {
if (node == null) {
return 0;
}
else {
return 1 + Math.max(depth(node.leftChild), depth(node.rightChild));
}
}
public static void findSum( Node node, int sum) {
int depth = depth(node);
int[] path = new int[depth];
findSum(node, sum, path, 0);
}
private static void print(int[] path, int start, int end) {
for (int i = start; i <= end; i++) {
System.out.print(path[i] + " ");
}
System.out.println();
}
// END PATH ALGORITHM
public static void main(String[] args) {
int[] myArr = {5, 3, 1, 4, 8, 2, 6};
// int[] myArr = { 10,32,63,44,115,66,7,18,999 }; // sortedArrayToBST
BinaryTree myTr = new BinaryTree();
for( int j=0; j < myArr.length; j++){
myTr.addNode(myArr[j]);
}
// Node n = BinaryTree.createMinimalBST(myArr);
/*question 4-3
create a binary tree with minimal height ( balanced tree )*/
/*myTr.createMinimalBST(myArr);*/
// System.out.println("The root is = "+myTr.root);
myTr.inOrderTraverseTree(myTr.root);
System.out.println("\n\n");
/*get the height of the binary search tree*/
/*System.out.println( "the height of the tree is = "+myTr.height(myTr.root));
System.out.println("\n\n");*/
/*question 4-1
check whether the tree is balanced */
/*boolean isBalanced = myTr.isBalanced(myTr.root);
if (isBalanced) {
System.out.println("The tree is balanced \n\n");
}*/
/*question 4-4
create a linked list of all the nodes in the same level of the BST
breadth first search ( BFS ) is used for implementation */
/*ArrayList<LinkedList<Node>> list = createLevelLinkedList(myTr.root);
printResult(list);*/
/* ge parent of the elements */
/*
for(int j = 0; j < myArr.length ; j++){
int checkParent = myArr[j];
System.out.println("the parent of "+ checkParent +" is = "+ myTr.getParent( checkParent) );
}
*/
// using an integer value, get the node that contains that int element
/*Node myNode = myTr.getNode(44);
System.out.println("Get my node = "+ myNode.key ); */
/* get in-order successive node of certain node */
/*int getInOrderSuccessive = 44 ;
System.out.println( myTr.inorderSucc( myTr.getNode( getInOrderSuccessive)) );*/
/* question 4-6
get the first common ancestor of two nodes */
/*int firstNodeInteger = 7;
int secondNodeInteger = 66;
// try the first solution
System.out.println( myTr.commonAncestor( myTr.root, myTr.getNode(firstNodeInteger), myTr.getNode(secondNodeInteger) ));
// try the second solution
System.out.println( myTr.commonAncestor2( myTr.root, myTr.getNode(firstNodeInteger), myTr.getNode(secondNodeInteger) ));
*/
/* question 4-7 */
/* check whether one tree is sub-set of the another tree */
/*
int[] array1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
int[] array2 = {2, 4, 5, 8, 9, 10, 11};
Node t1 = myTr.createTreeFromArray(array1);
Node t2 = myTr.createTreeFromArray(array2);
if (containsTree(t1, t2))
System.out.println("t2 is a subtree of t1");
else
System.out.println("t2 is not a subtree of t1");
int[] array3 = {1, 2, 3};
Node t3 = myTr.createTreeFromArray(array1);
Node t4 = myTr.createTreeFromArray(array3);
if (containsTree(t3, t4))
System.out.println("t4 is a subtree of t3");
else
System.out.println("t4 is not a subtree of t3");
*/
/* question 4-8
algorithm to get all the paths equal to given value */
/*int testValue = 7;
myTr.findSum( myTr.root, testValue );*/
}
}
Just use the root in your bbst() method instead of declaring n.
public void bbst(int array[]) {
root = new TreeNode();
balancedBST(array, 0, array.length - 1, root);
}
I can't see the balancedBST in your code. Did you mean the method createMinimalBST(int arr[], int start, int end, Node newNode)?
If so, then based on this call
createMinimalBST(array, 0, array.length - 1, root)
I deduce start and end parameters are inclusive indices of the subarray to be converted into a subtree. For the single-item array you have start == end — but then the first line of the method will discard that item:
if ( end <= start ) return;
leaving you with a new node with no key assigned.
And the whole method is overcomplicated and thus unreadable. KISS! For example:
private Node createBalancedTree(int arr[], int start, int end){
if ( end < start ) return null; // empty array -> empty tree
int mid = start + (end - start) / 2; // avoid overflow
// create a tip node
Node node = new Node( arr[mid] );
// convert remaining subarrays (if any) into subtrees
node.leftChild = createBalancedTree( arr, start, mid - 1 );
node.rightChild = createBalancedTree( arr, mid + 1, end );
return node;
}
public void createBalancedTree( int array[] ) {
// convert the array into a tree and plant it in this
root = createBalancedTree( array, 0, array.length - 1 );
}
Note however I removed 'BS' from the method name. The routine never checks the ordering of array items, so the resulting tree is balanced, but might be NOT-BST if the array isn't sorted!
If you want the resulting tree with a proper ordering you either need to sort the array prior to the 'build-a-tree' call or you have to add nodes one by one with an addNode(int key) method.
And if you want to build a balanced BST, then you need a new addNodeBalanced method...
(There is a load of other issues with your code, like a forever-recurring height(Node root), but I limit myself here to the part you pointed in your question.)
EDIT
The note about height(Node root) turned out to be false.

Counting the inner nodes (parent nodes) in a binary tree recursively

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 inner nodes in the entire binary search tree.
This is what I have so far:
int countNrOfInnerNodes (Node node) {
if(node == null) {
return 0;
}
if (node.left != null && node.right != null){
return 1;
}
return countNrOfInnerNodes(node.left)+countNrOfInnerNodes(node.right)
}
}
Is there a better way? I also stuck to find a iterativ solution.
Here's the recursive method fixed:
int countNrOfInnerNodes (Node node) {
if(node == null) {
return 0;
}
if (node.left == null && node.right == null) {
// not an inner node !
return 0;
} else {
// the number of inner nodes in the left sub-tree + the number of inner
// nodes in the right sub-tree, plus 1 for this inner node
return countNrOfInnerNodes(node.left) + countNrOfInnerNodes(node.right) + 1;
}
}
Here's the iterative method:
int countNrOfInnerNodes(Node node) {
if (node == null)
return 0;
Stack<Node> nodesToCheck = new Stack<Node>();
nodesToCheck.push(node);
int count = 0;
while (!nodesToCheck.isEmpty()) {
Node checkedNode = nodesToCheck.pop();
boolean isInnerNode = false;
if (node.left != null) {
isInnerNode = true;
nodesToCheck.push(node.left);
}
if (node.right != null) {
isInnerNode = true;
nodesToCheck.push(node.right);
}
if (isInnerNode)
count++;
}
return count;
}

Why won't my delete function delete the node out of the BST?

I've spent hours trying to figure it out. I've checked and the delete function does find the node, but when I try to delete it by setting it as null or equal to a child node it doesn't change the tree at all when I print it out for a second time. Can anyone help me figure out what I've done wrong or at least guide me to what I need to do to fix it?
class BST {
Node root;
void BST () {
root = new Node("B");
insert (root, "A");
insert (root, "D");
insert (root, "C");
inOrder (root);
System.out.println (" ");
delete (root, "D");
//root.LEFT = null;
inOrder (root);
}
void insert (Node n, String newKEY) {
if (n.KEY.compareTo(newKEY) > 0) {
if (n.LEFT == null) n.LEFT = new Node(newKEY);
else if (n.LEFT != null && n.LEFT.KEY.compareTo(newKEY) < 0) n.LEFT = new Node(n.LEFT, newKEY, null);
else insert (n.LEFT, newKEY);
}
if (n.KEY.compareTo(newKEY) < 0) {
if (n.RIGHT == null) n.RIGHT = new Node(newKEY);
else if (n.RIGHT != null && n.RIGHT.KEY.compareTo(newKEY) > 0) n.RIGHT = new Node(null, newKEY, n.RIGHT);
else insert (n.RIGHT, newKEY);
}
else if (n.KEY.compareTo(newKEY) == 0) n.C++;
}
void delete (Node n, String s) {
// Visit, check if proper node, if so then delete
if (n.KEY.compareTo(s) == 0) {
System.out.println (n.KEY);
// Deleting a node with no children
if (n.LEFT == null && n.RIGHT == null) n = null;
// Deleting a node with only left child
else if (n.RIGHT == null) n = n.LEFT;
// Deleting a node with only right child
else if (n.LEFT == null) n = n.RIGHT;
// Deleting a node with two children
else deleteNode_Two_Children (n, s);
}
// Left
else if (n.KEY.compareTo(s) > 0) delete (n.LEFT, s);
// Right
else if (n.KEY.compareTo(s) < 0) delete (n.RIGHT, s);
}
boolean find (Node n, String s) {
if (n.KEY.compareTo(s) > 0) {
if (n.LEFT == null) return false;
else if (n.LEFT != null && n.LEFT.KEY.compareTo(s) < 0) return false;
else find (n.LEFT, s);
}
if (n.KEY.compareTo(s) < 0) {
if (n.RIGHT == null) return false;
else if (n.RIGHT != null && n.RIGHT.KEY.compareTo(s) > 0) return false;
else find (n.RIGHT, s);
}
else if (n.KEY.compareTo(s) == 0) return true;
return false;
}
void deleteNode_Two_Children (Node n, String st) {
Node s = getSuccessor(n);
n = new Node (n.LEFT, s.KEY, s.C, n.RIGHT);
delete (s, st);
}
Node getSuccessor (Node n) {
Node temp = new Node();
while (n.LEFT != null) {
temp = n.LEFT;
n = temp;
}
return temp;
}
void inOrder (Node n) {
// Left
if (n.LEFT != null) inOrder (n.LEFT);
// Visit
System.out.print (n.KEY + " - " + n.C + ", ");
// Right
if (n.RIGHT != null) inOrder (n.RIGHT);
}
public static void main(String args[]){
BST t = new BST();
t.BST();
}
}
class Node {
String KEY;
int C;
Node LEFT;
Node RIGHT;
Node (String key) {
KEY = key;
C = 1;
LEFT = null;
RIGHT = null;
}
Node (Node L, String key, Node R) {
LEFT = L;
RIGHT = R;
KEY = key;
C = 1;
}
Node (Node L, String key, int c, Node R) {
LEFT = L;
RIGHT = R;
KEY = key;
C = c;
}
Node () {
KEY = null;
C = 0;
LEFT = null;
RIGHT = null;
}
// If 'this' is less than 'other', a negative number will be returned,
// 0 if equal
// Positive number if 'this' is greater.
int compare (Node other) {
return this.KEY.compareTo(other.KEY);
}
boolean equals (Node other) {
return this.KEY.equals(other.KEY);
}
}
The problem is your assumption that setting n to null will remove the node. Consider the following:
Object x = new Object();
public void someMethod(Object o) {
o = null;
}
This won't modify x. Java is pass-by-value, where o is the reference to some Object. You can certainly modify the internals of o through o's methods:
o.setValue(1);
This works because the value of o is really some address on the heap, which isn't being modifed. You can't overwrite o itself (eg, you can't set it to null or a new Object()). In order for you to delete a node, you must find the node's parent and set it's left or right child (whichever one you with to remove) and set that to null. Also, if that node has children, you have to make sure they aren't removed just because their parent is removed.

Categories

Resources