Binary Search tree code without the parameters? - java

I have the following code.
But it is expected to be without parameters for example sum() and i am not quite sure on how to fix that so that the code would still work. Could someone help me with that?
I would like change the code as little as possible.
is there a way to add it to the methods and the recall the recusive methods from that
import java.util.*;
public class BinarySearchTree {
private class BinaryNode {
private int element;
private BinaryNode left;
private BinaryNode right;
private BinaryNode(int element) {
this.element = element;
}
}
private BinaryNode root;
public void insert(int newNumber) {
// special case: empty tree
if (root == null) {
root = new BinaryNode(newNumber);
return;
}
BinaryNode parent = null;
BinaryNode child = root;
while (child != null) {
parent = child;
if (newNumber == child.element) {
//number already in tree
return;
} else if (newNumber < child.element) {
child = child.left;
} else {
child = child.right;
}
}
if (newNumber < parent.element) {
parent.left = new BinaryNode(newNumber);
} else {
parent.right = new BinaryNode(newNumber);
}
}
public int maximumRecursive(BinaryNode root) {
if (root.right == null)
return root.element;
return maximumRecursive(root.right);
}
public int maximumIterative() {
if (root == null) {
throw new NoSuchElementException();
}
BinaryNode current = root;
while (current.right != null)
current = current.right;
return (current.element);
}
public int height(BinaryNode root) {
if (root == null)
return 0;
return 1 + Math.max(height(root.left), height(root.right));
}
public int sum(BinaryNode root) {
if (root == null)
return 0;
return root.element + sum(root.left) + sum(root.right);
}
public String reverseOrder(BinaryNode root) {
if (root == null) {
return "";
}
return reverseOrder(root.right) + " " + ((Integer) root.element).toString() + " " + reverseOrder(root.left);
}

You can just overload your sum method, so you have the version with parameter, and without parameter. Make the one with parameter private, as that version should only be used during the recursive deepening (inside the class):
private int sum(BinaryNode root) {
if (root == null)
return 0;
return root.element + sum(root.left) + sum(root.right);
}
public int sum() {
return sum(root);
}
You can do a similar thing for the other methods that are recursive, and for that reason have a parameter. For instance, for height:
private int height(BinaryNode root) {
if (root == null)
return 0;
return 1 + Math.max(height(root.left), height(root.right));
}
public int height() {
return height(root);
}

Related

How can i use inner class in outer class in Java?

Im trying to develop Bynary Tree on Java. I have 2 classes BynaryTreeMap and his inner class Elem.
public class Main {
public static void main(String[] args) {
BinaryTreeMap tree = new BinaryTreeMap(22);
System.out.println(tree.MapSearch(22));
tree.insert(10);
System.out.println(tree);
}
}
class BinaryTreeMap {
Elem root;
private static int height;
BinaryTreeMap(int key){
root = new Elem(key);
height = 1;
}
public Elem next(Elem elem){
Elem next;
if (elem.right != null) {
next = this.Minimum(elem.right);
}
else{
next = elem.parent;
while (next != null && elem == next.right){
elem = next;
next = next.parent;
}
}
return next;
}
public void insert(int key){
Elem elem = new Elem(key);
Elem x;
if (root == null)
root = elem;
else {
x = root;
while(true){
if (x.key == key)
throw new RuntimeException("elem is already in tree");
if (key < x.key){
if (x.left == null){
x.setLeft(elem);
break;
}
x = x.left;
}
else
if (x.right == null){
x.setRight(elem);
break;
}
x = x.right;
}
}
}
public Elem descend(int key){
Elem elem = root;
while (elem != null && elem.key != key){
if (key <= elem.key)
elem = elem.left;
else elem = elem.right;
}
return elem;
}
public boolean MapSearch(int key){
return descend(key) != null;
}
public Elem lookUp(int key){
Elem elem = descend(key);
if (elem == null)
throw new RuntimeException("No such elemet");
return elem;
}
public boolean isEmpty(){
return root == null;
}
public Elem Minimum(Elem elem){
Elem min = elem;
while (min.left != null)
min = min.left;
return min;
}
public Elem Maximum(Elem elem){
Elem max = elem;
while (max.right != null)
max = max.right;
return max;
}
#Override
public String toString() {
StringBuilder stringBuilder = new StringBuilder("BinaryTreeMap{");
while (root != null){
stringBuilder.append(root.key);
root = this.next(root);
}
stringBuilder.append("}");
return stringBuilder.toString();
}
public class Elem{
private Elem parent = null;
private Elem left = null;
private Elem right = null;
private final int key;
Elem(int key){
this.key = key;
}
private void setLeft(Elem leftAncestor){
this.left = leftAncestor;
leftAncestor.parent = this;
}
private void setRight(Elem rightAncestor){
this.right = rightAncestor;
rightAncestor.parent = this;
}
}
}
Output
true
BinaryTreeMap{22}
If i run the program in debug mode, my output is worse.
false
BinaryTreeMap{}
Correct output
true
BinaryTreeMap{22 10}
As i can see my root variable became null, but i cant understand why.
Tried to google it, bud didnt succeed. Maybe i didnt uderstand how inner classes work?
Thank you for you help.

Problem with recursive method for BST rRemove(BSTNode<T> current, T data, BSTNode<T> dummy) when using pointer reinforcement technique

Here is the Node class:
public class BSTNode<T extends Comparable<? super T>> {
private T data;
private BSTNode<T> left;
private BSTNode<T> right;
BSTNode(T data) {
this.data = data;
}
T getData() {
return data;
}
BSTNode<T> getLeft() {
return left;
}
BSTNode<T> getRight() {
return right;
}
void setData(T data) {
this.data = data;
}
void setLeft(BSTNode<T> left) {
this.left = left;
}
void setRight(BSTNode<T> right) {
this.right = right;
}
}
Here is my BST class with main driver method:
import java.util.NoSuchElementException;
public class BST<T extends Comparable<? super T>> {
private BSTNode<T> root;
private int size;
BST() {
root = null;
}
public void add(T data) {
if (data == null) {
throw new IllegalArgumentException("Error: Data can't be null");
}
root = rAdd(root, data);
}
private BSTNode<T> rAdd(BSTNode<T> current, T data) {
if (current == null) {
size++;
return new BSTNode<T>(data);
} else if (data.compareTo(current.getData()) < 0) {
current.setLeft(rAdd(current.getLeft(), data));
} else if (data.compareTo(current.getData()) > 0) {
current.setRight(rAdd(current.getRight(), data));
}
return current;
}
public T remove(T data) {
if (data == null) {
throw new IllegalArgumentException("Error: data can't be null");
}
BSTNode<T> dummy = new BSTNode<>(null);
root = rRemove(root, data, dummy);
return dummy.getData();
}
private BSTNode<T> rRemove(BSTNode<T> current, T data, BSTNode<T> dummy) {
if (current == null) {
throw new NoSuchElementException("Error: Data not present");
} else if (data.compareTo(current.getData()) < 0) {
current.setLeft(rRemove(current.getLeft(), data, dummy));
} else if (data.compareTo(current.getData()) > 0) {
current.setRight(rRemove(current.getRight(), data, dummy));
} else {
System.out.println("Data found ... ");
dummy.setData(current.getData());
size--;
if (current.getRight() == null && current.getLeft() == null) {
if (current.equals(root)) {
this.root = null;
}
return null;
} else if (current.getLeft() != null) {
return current.getLeft();
} else if (current.getRight() != null) {
return current.getRight();
} else {
BSTNode<T> dummy2 = new BSTNode<>(null);
current.setRight(removeSuccessor(current.getRight(), dummy2));
current.setData(dummy2.getData());
}
}
return current;
}
private BSTNode<T> removeSuccessor(BSTNode<T> current, BSTNode<T> dummy) {
if (current.getLeft() == null) {
dummy.setData(current.getData());
return current.getRight();
} else {
current.setLeft(removeSuccessor(current.getLeft(), dummy));
}
}
public List<T> inorder(BSTNode<T> root) {
ArrayList<T> inorderContents = new ArrayList<T>();
if (root == null) {
return inorderContents;
}
inorderR(inorderContents, root);
return inorderContents;
}
private void inorderR(ArrayList<T> inorderContents, BSTNode<T> current) {
if (current == null) {
return;
}
inorderR(inorderContents, current.getLeft());
inorderContents.add(current.getData());
inorderR(inorderContents, current.getRight());
}
public BSTNode<T> getRoot() {
// DO NOT MODIFY THIS METHOD!
return root;
}
public int size() {
// DO NOT MODIFY THIS METHOD!
return size;
}
public static void main(String[] args) {
BST bst3 = new BST<>();
bst3.add(1);
bst3.add(0);
bst3.add(5);
bst3.add(4);
bst3.add(2);
bst3.add(3);
System.out.println(bst3.inorder(bst3.getRoot() ));
bst3.remove(1);
System.out.println(bst3.inorder(bst3.getRoot() ));
}
}
My IDE (IntelliJ) says I am missing a return statement for my removeSuccessor(BSTNode current, BSTNode dummy) method but I expected it to recurse to the base case reinforcing the unchanged nodes.
As a result when I try and remove from a two child node it returns zero although the one child and zero child cases work .
Please can someone tell me what is wrong with my two child node remove case? Thanks, Sperling.
First, you need to modify the if-else by changing the conditions:
if (current.getLeft() != null && current.getRight() == null) {
return current.getLeft();
} else if (current.getRight() != null && current.getLeft() == null) {
return current.getRight();
}
instead of the same without the 2nd arguments of && in the rRemove() method.
Then, use this:
private BSTNode<T> removeSuccessor(BSTNode<T> current, BSTNode<T> dummy) {
if (current.getLeft() == null) {
dummy.setData(current.getData());
return current.getRight();
} else {
current.setLeft(removeSuccessor(current.getLeft(), dummy));
return current;
}
}
Meaning of this method is as follows: delete the lowest value in the tree and return new root, as well as remember the value using dummy.
If we get nothing to the left, it's trivial - we delete current node, return getRight() and set a value to dummy.
On the other hand, if we get something to the left then we know that our current node will be the root, but before we return it we need to remove the lowest entry to the left, and so we use the function recursively, also setting current.left to be it's return value to properly transform the tree. We pass dummy so that it can get a value when the first case occurs, and then it's communicated to the highest call (inside the first function).
It's also possible to do it without recursion:
private BSTNode<T> removeSuccessor2(BSTNode<T> current, BSTNode<T> dummy) {
BSTNode<T> root = current;
BSTNode<T> prev = null;
while(current.getLeft() != null) {
prev = current;
current = current.getLeft();
}
/* current.getLeft == null */
//we will delete current
if (prev == null) { //no loop iterations -- current is the root
dummy.setData(current.getData());
return(current.getRight());
}
else {//some iterations passed, prev.getLeft() == curret
dummy.setData(current.getData());
prev.setLeft(current.getRight());
return root;
}
}
With dummy we return the value, the rest is transforming the tree.
Note: It doesn't work in my version for current == null. You should be able to modify it easily, though. Also, for clarity I didn't pull the dummy.setData... before if...else etc. Modify it as you wish!

How do I reference a method to add to a binaryTree?

I am tasked with building a BinaryTree that represents Morse Code. It branches left with each dot and right with each dash.
I can not figure out, however, why my method to add a Node does not seem to want to work with a BinaryTree object. IntelliJ says that it "can not resolve method".
I am certain that the BinaryTree is not the issue, because I was given detailed instructions on how to write the class by my instructor. Rather, I suspect that I am perhaps referencing the wrong thing here. I have already verified that the parameters being entered isn't the issue.
public static MorseCodeTree<Character> readMorseCodeTree()
{
MorseCodeTree<Character> morse = new MorseCodeTree<Character>();
Node<Character> newNode = new Node<Character>(null);
morse.addNode(newNode, letter, position);
private Node<Character> addNode(Node<Character> currentNode, char data, String morseCode)
{
if (currentNode == null)
{
currentNode = new Node(null);
}
if (morseCode.charAt(0) == '*')
{
currentNode = addNode(currentNode.left, data, morseCode.substring(1));
}
else if (morseCode.charAt(0) == '-')
{
currentNode = addNode(currentNode.right, data, morseCode.substring(1));
}
else
{
currentNode.data = data;
}
return currentNode;
}
BinaryTree class:
import java.io.Serializable;
import java.util.Scanner;
public class BinaryTree implements Serializable{
//implement Node class
protected static class Node<E> implements Serializable
{
protected E data;
protected Node<E> left;
protected Node<E> right;
public Node (E data)
{
this.data = data;
this.left = null;
this.right = null;
}
public String toString()
{
return data.toString();
}
}
protected Node root;
public BinaryTree()
{
root = null;
}
protected BinaryTree(Node<E> root)
{
this.root = root;
}
public BinaryTree(E data, BinaryTree<E> leftTree, BinaryTree<E> rightTree)
{
root = new Node<E>(data);
if (leftTree != null)
{
root.left = leftTree.root;
}
else
{
root.left = null;
}
if (rightTree != null)
{
root.right = rightTree.root;
}
else
{
root.right = null;
}
}
public BinaryTree<E> getLeftSubtree()
{
if (root != null && root.left != null)
{
return new BinaryTree<E>(root.left);
}
else
{
return null;
}
}
public BinaryTree<E> getRightSubtree()
{
if (root != null && root.right != null)
{
return new BinaryTree<E>(root.right);
}
else
{
return null;
}
}
public boolean isLeaf()
{
return (root.left == null && root.right == null);
}
public String toString()
{
StringBuilder sb = new StringBuilder();
preOrderTraverse(root, 1, sb);
return sb.toString();
}
private void preOrderTraverse(Node<E> node, int depth, StringBuilder sb)
{
for (int i = 1; i < depth; i++)
{
sb.append(" ");
}
if (node == null)
{
sb.append("null\n");
}
else
{
sb.append(node.toString() + "\n");
preOrderTraverse(node.left, depth + 1, sb);
preOrderTraverse(node.right, depth + 1, sb);
}
}
public static BinaryTree<String> readBinaryTree(Scanner scan)
{
String data = scan.next();
if (data.equals("null"))
{
return null;
}
else
{
BinaryTree<String> leftTree = readBinaryTree(scan);
BinaryTree<String> rightTree = readBinaryTree(scan);
return new BinaryTree<String>(data, leftTree, rightTree);
}
}
}
You're declaring the addNode(...) method within readMorseCodeTree(), so it's not in the scope of the class. The latter method should look like this:
public static BinaryTree<Character> readMorseCodeTree()
{
BinaryTree morse = new MorseCodeTree();
Node<Character> newNode = new Node<Character>(null);
morse.addNode(newNode, letter, position);
}

Binary search tree Searching troubleshooting

I've spent about two days pouring over this and I have no idea what's missing. Originally my BST used comparables, then I switched it to int to simplify it when it wasn't working.
I add several items to a tree and it successfully prints them out in order. Then, the first time I call the search() method it returns true, as it should. Every other search call after that returns false whether it is true or false.
I'm including most of my code here in case the problem isn't related with the search method itself.
The output SHOULD be: 4 12 23 27 30 42 60 84 true true false true true
but instead I get: 4 12 23 27 30 42 60 84 true false false false false
public class BSTree {
TreeNode root;
static int comparison;
public void insert(int value) {
if (root == null) {
root = new TreeNode(value);
}
else {
root.insert(value);
}
}
public boolean search(int chicken) {
if (root != null ) {
return root.search(chicken);
}
return false;
}
public static int height(TreeNode b) {
return TreeNode.height(b);
}
public static void CompareSet() {
comparison++;
}
public int getCompare() {
return comparison;
}
public void ResetCompare() {
comparison = 0;
}
public static void traverseInOrder (TreeNode node) {
if (node != null) {
traverseInOrder(node.left);
System.out.print(" " + node.data);
traverseInOrder (node.right);
}
}
public static void main(String args[]) {
BSTree tree = new BSTree();
tree.insert(30);
tree.insert(42);
tree.insert(84);
tree.insert(12);
tree.insert(4);
tree.insert(23);
tree.insert(27);
tree.insert(60);
traverseInOrder(tree.root);
System.out.println("\n" + tree.search(30));
System.out.println("\n" + tree.search(4));
System.out.println("" + tree.search(50));
System.out.println("" + tree.search(27));
System.out.println("" + tree.search(42));
System.out.println(height(tree.root));
}
}
Here is the treeNode class:
public class TreeNode<T> {
int data;
TreeNode left;
TreeNode right;
TreeNode(int value){
this.data = value;
//right = null;
//left = null;
}
public void insert(int value) {
if (value == data) {
return;
}
if (value < data) {
if (left == null) {
left = new TreeNode(value);
}
else {
left.insert(value);
}
}
else {
if (right == null) {
right = new TreeNode(value);
}
else {
right.insert(value);
}
}
public boolean search(int value) {
BSTree.CompareSet();
if (data == value) return true;
if (data < value && left!=null)
return left.search(value);
else if(data > value && right != null)
return right.search(value);
return false;
}
public static int height(TreeNode b) {
if (b == null) return -1;
return 1 + Math.max(height(b.left), height(b.right));
}
public int getData(){
return data;
}
public TreeNode getLeftChild() {
return left;
}
public void setLeftChild(TreeNode leftChild) {
this.left = leftChild;
}
public TreeNode getRightChild() {
return right;
}
public void setRightChild(TreeNode rightChild) {
this.right = rightChild;
}
}
Your comparaisons are reversed :))) Here is the corrected TreeNode::search method :
public boolean search(int value) {
BSTree.CompareSet();
if (data == value) return true;
if (data > value && left!=null)
return left.search(value);
else if(data < value && right != null)
return right.search(value);
return false;
}
I think you swapped the data and the value variables.
just change your search method of TreeNode class to this:
public boolean search(int value) {
Test.CompareSet();
if (data == value) return true;
if (data < value && right!=null)
return right.search(value);
else if(data > value && left != null)
return left.search(value);
return false;
}
When your current node's data is greater than value you need to go to left sub-tree. And when current node's data is smaller than value you need to go to right sub-tree. You just have done the reverse one.

Java Generics: compareTo and “capture#-of ?”

I'm trying to write an implementation of a BinaryTree whose object can be of any type that implements Comparable. However, I realize that won't completely work. For example, A String and a Double wouldn't be able to be inserted into the same tree, even though they both implement Comparable.
So, I would like to know if it's possible to write the code such that the BinaryTree can be instantiated with any value whose type implements Comparable, but any ensuing elements added to the tree must all share the same supertype as the root's value.
Here's the code I have so far:
public class BinaryTree {
private Node root;
public BinaryTree() {
this.root = null;
}
public Node lookup(Comparable<Object> value) {
return lookup(this.root, value);
}
private Node lookup(Node node, Comparable<Object> value) {
Node match = null;
if (match != node) {
if (value == node.value) {
match = node;
} else if (value.compareTo(node.value) < 0) {
return lookup(node.left, value);
} else {
return lookup(node.right, value);
}
}
return match;
}
public Node lookupNonRecursively(Comparable<Object> value) {
return lookupNonRecursively(this.root, value);
}
private Node lookupNonRecursively(Node node, Comparable<Object> value) {
Node match = null;
if (match != node) {
if (value == node.value) {
match = node;
} else {
Node root = node;
boolean found = false;
while (!found && root != null) {
if (root.value.compareTo(value) < 0) {
if (root.left == null) {
root.left = match = new Node(value);
found = true;
} else {
root = root.left;
}
} else {
if (root.right == null) {
root.right = match = new Node(value);
found = true;
} else {
root = root.right;
}
}
}
}
}
return match;
}
public Node insert(Comparable<Object> value) {
return insert(this.root, value);
}
private Node insert(Node node, Comparable<Object> value) {
if (node == null) {
node = new Node(value);
} else {
if (node.value.compareTo(value) <= 0) {
insert(node.left, value);
} else {
insert(node.right, value);
}
}
return node;
}
public Node insertNonRecursively(Comparable<Object> value) {
return insertNonRecursively(this.root, value);
}
private Node insertNonRecursively(Node node, Comparable<Object> value) {
if (node == null) {
node = new Node(value);
} else {
Node root = node;
boolean inserted = false;
while (!inserted) {
if (node.value.compareTo(root.value) < 0) {
if (root.left == null) {
root.left = node = new Node(value);
inserted = true;
} else {
root = root.left;
}
} else {
if (root.right == null) {
root.right = node = new Node(value);
inserted = true;
} else {
root = root.right;
}
}
}
}
return node;
}
public static class Node {
private Node left;
private Node right;
private Comparable<Object> value;
public Node(Comparable<Object> value) {
this.left = null;
this.right = null;
this.value = value;
}
}
}
And as a test, this will throw the error, The method insert(Comparable<Object>) in the type BinaryTree is not applicable for the arguments (Integer), if I try to run code like the following:
BinaryTree tree = new BinaryTree();
tree.insert(new Integer(1));
You can see I've implemented some different BinaryTree methods for this class, but the same rules would need to apply: any value passed into lookup() or insert() would also need to share the root's supertype. I have a feeling this is where some variant of <T extends Comparable<? super T>> is going to come into play, but my mind is just not figuring this one out.
Any ideas for how I might accomplish this?
As noted by #jp-jee, here's my solution (also with logic and other bugs fixed from untested first attempt), which works beautifully:
public class BinaryTree<T extends Comparable<T>> {
private Node<T> root;
public BinaryTree() {
this.root = null;
}
public Node<T> lookup(T value) {
return lookup(this.root, value);
}
private Node<T> lookup(Node<T> node, T value) {
Node<T> match = null;
if (match != node) {
if (value.equals(node.value)) {
match = node;
} else if (value.compareTo(node.value) < 0) {
return lookup(node.left, value);
} else {
return lookup(node.right, value);
}
}
return match;
}
public Node<T> lookupNonRecursively(T value) {
return lookupNonRecursively(this.root, value);
}
private Node<T> lookupNonRecursively(Node<T> node, T value) {
Node<T> match = null;
if (match != node && value != null) {
if (value.equals(node.value)) {
match = node;
} else {
Node<T> searchRoot = node;
boolean found = false;
while (!found && searchRoot != null) {
if (value.equals(searchRoot.value)) {
match = searchRoot;
found = true;
} else if (value.compareTo(searchRoot.value) < 0) {
searchRoot = searchRoot.left;
} else {
searchRoot = searchRoot.right;
}
}
}
}
return match;
}
public void insert(T value) {
this.root = insert(this.root, value);
}
private Node<T> insert(Node<T> node, T value) {
if (node == null) {
node = new Node<T>(value);
} else {
if (value.compareTo(node.value) <= 0) {
node.left = insert(node.left, value);
} else {
node.right = insert(node.right, value);
}
}
return node;
}
public void insertNonRecursively(T value) {
this.root = insertNonRecursively(this.root, value);
}
private Node<T> insertNonRecursively(Node<T> node, T value) {
if (node == null) {
node = new Node<T>(value);
} else {
Node<T> runner = node;
boolean inserted = false;
while (!inserted) {
if (value.compareTo(runner.value) < 0) {
if (runner.left == null) {
runner.left = new Node<T>(value);
inserted = true;
} else {
runner = runner.left;
}
} else {
if (runner.right == null) {
runner.right = new Node<T>(value);
inserted = true;
} else {
runner = runner.right;
}
}
}
}
return node;
}
public static class Node<T extends Comparable<T>> {
private Node<T> left;
private Node<T> right;
private T value;
public Node(T value) {
this.left = null;
this.right = null;
this.value = value;
}
public Node<T> getLeft() {
return left;
}
public Node<T> getRight() {
return right;
}
public T getValue() {
return value;
}
}
}
Make your Binary Tree generic like
public class BinaryTree<T extends Comparable<T>>{
...
}
Whenever creating a BinaryTree instance, specify the containied type:
new BinaryTree<MyClass>();
Where MyClass must implement Comparable<MyClass>, i.e. be comparable to Objects of the same class.
Your methods would read as (example):
public Node lookup(T value) { ... }
The same applies for your Node class. Make it generic the same way.

Categories

Resources