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.
Related
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);
}
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);
}
I am currently trying to understand Singly linked lists.
I don't understand some of the code in the SinglyLinkedList.java class. How can the Node class be called and then assigned like: private Node first;
I would have thought that you would have to do something like this
Node<T> help =new Node<>();
help = first;
If someone could explain, or provide me to a link that would help me, it would be much appreciated.
Thanks!
public class Node<T> {
public T elem;
public Node<T> next;
public Node(T elem) {
this.elem = elem;
next = null;
}
public Node(T elem, Node<T> next) {
this.elem = elem;
this.next = next;
}
#Override
public String toString() {
return "Node{" + "elem=" + elem + '}';
}
}
package list;
/**
*
* #author dcarr
*/
public class SinglyLinkedList<T> implements List<T> {
private Node<T> first;
private Node<T> last;
public SinglyLinkedList() {
first = null;
last = null;
}
#Override
public boolean isEmpty() {
return first == null;
}
#Override
public int size() {
if (isEmpty()){
return 0;
} else {
int size = 1;
Node<T> current = first;
while(current.next != null){
current = current.next;
size++;
}
return size;
}
}
#Override
public T first() {
return first.elem;
}
#Override
public void insert(T elem) {
// if there is nothing in the list
if (isEmpty()){
first = new Node<>(elem);
last = first;
// if the list has elements already
} else {
// the new element will be the next of what was the last element
last.next = new Node<>(elem);
last = last.next;
}
}
#Override
public void remove(T elem) {
if (!isEmpty()){
int index = 0;
Node<T> current = first;
while (current != null && current.elem != elem){
current= current.next;
index++;
}
remove(index);
}
}
#Override
public String toString() {
if (isEmpty()){
return "Empty List";
} else {
String str = first.elem.toString() + " ";
Node<T> current = first;
while(current.next != null){
current = current.next;
str += current.elem.toString() + " ";
}
return str;
}
}
#Override
public void insertAt(int index, T e) {
if (index == 0){
first = new Node<>(e, first);
if (last == null){
last = first;
}
return;
}
Node<T> pred = first;
for (int i = 0; i < index-1; i++) {
pred = pred.next;
}
pred.next = new Node<>(e, pred.next);
System.out.println(pred);
if (pred.next.next == null){
// what does this mean pred.next is?
last = pred.next;
}
}
#Override
public void remove(int index) {
if (index < 0 || index >= size()){
throw new IndexOutOfBoundsException();
} else if (isEmpty()){
return;
}
if (index == 0){
first = first.next;
if (first == null){
last = null;
}
return;
}
Node<T> pred = first;
for (int i = 1; i <= index-1; i++) {
pred = pred.next;
}
// remove pred.next
pred.next = pred.next.next;
if (pred.next == null){
last = pred;
}
}
}
The first field is automatically initialized to null:
private Node<T> first;
I assume there will be some method to add an element at the end like so:
public void add(T element) {
if (first == null) {
first = new Node<T>(element);
last = first;
}
else {
last.next = new Node<>(element);
last = last.next;
}
}
So when you create a new SinglyLinkedList:
SinglyLinkedList<String> sillyList = new SinglyLinkedList<>();
The first and last fields both hold a null reference.
Note that the first method will cause a NullPointerException at this point. A better implementation would be:
#Override
public Optional<T> first() {
if (first != null) {
return Optional.ofNullable(first.elem);
}
else {
return Optional.empty();
}
}
Now if you add an element:
sillyList.add("Adam");
The code executed in the add method is:
first = new Node<>(elem);
last = first;
So first points to a new Node instance with an elem field holding the value "Adam". And last points to that same Node instance.
Some of the methods in this class I would implement differently, for example:
#Override
public void remove(int index) {
if (index < 0) {
throw new IndexOutOfBoundsException("Index cannot be negative");
}
else if (index == 0 && first != null) {
first = null;
last = null;
}
else {
Node<T> curr = new Node<>("dummy", first);
int c = 0;
while (curr.next != null) {
if (c == index) {
curr.next = curr.next.next;
if (curr.next == null) {
last = curr;
}
return;
}
curr = curr.next;
c++;
}
throw new IndexOutOfBoundsException(String.valueOf(c));
}
Also, some of the methods don't actually exist in the java.util.List interface, like insert, insertAt and first. So these methods must not have the #Override annotation.
This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 7 years ago.
So in simpletons, I am creating my own AVLTree data structure. Now when i add a new node into my tree, it seems to add fine.
EDIT: It doesnt seem to take into account my duplicates (nor add them to the original node's list by key).
But when i print the rootNode to see if it exists it doesn't exist. I can't figure out what the problem is with my add method.
Here is my AVLTree class:
package cw.util;
import java.util.ArrayList;
import java.util.Comparator;
public class AVLTree<K, V>
{
public class Node {
private K key;
private ArrayList<V> valuesList;
private Node left, right;
private int height;
public Node(K key, ArrayList<V> valuesList) {
this.key = key;
this.valuesList = valuesList;
this.height = 0;
}
public Node(V value) {
}
public void addToNode(V value) {
valuesList.add(value);
}
public K getKey() {
return key;
}
public ArrayList<V> getValues() {
return valuesList;
}
public Node getLeftChild() {
return left;
}
public Node getRightChild() {
return right;
}
public int getHeight() {
return height;
}
public Node getChildNodeFromSide(String side) {
switch(side) {
default: return null;
case "left": return left;
case "right": return right;
}
}
}
private Node rootNode;
private Comparator<K> comparator;
//Unused
public AVLTree() {
}
public AVLTree(Comparator<K> comparator) {
this.comparator = comparator;
this.rootNode = null;
}
public V insert(K key, V value) {
Node n = insert(key, value, rootNode);
if(n != null) {
for(V v : n.getValues())
System.out.println(v.toString());
System.out.println();
return value;
} else {
return null;
}
}
public Node insert(K key, V value, Node node) {
ArrayList<V> values = new ArrayList<V>();
values.add(value);
if(node == null)
node = new Node(key, values);
else if(comparator.compare(key, node.key) < 0) {
node.left = insert(key, value, node.left);
if(height(node.left) - height(node.right) == 2) {
if(comparator.compare(key, node.left.key) < 0)
node = rotateWithLeftChild(node);
else
node = doubleRotateWithLeft(node);
}
} else if(comparator.compare(key, node.key) > 0) {
node.right = insert(key, value, node.right);
if(height(node.right) - height(node.left) == 2) {
if(comparator.compare(key, node.right.key) > 0)
node = rotateWithRightChild(node);
else
node = doubleRotateWithRight(node);
}
} else node.getValues().add(value);
node.height = Math.max(height(node.left), height(node.right)) + 1;
return node;
}
public Node search(K key) {
return search(key, rootNode);
}
public Node search(K key, Node node) {
boolean isFound = false;
while((node != null) && !isFound) {
K nodeKey = node.getKey();
if(comparator.compare(key, nodeKey) < 0)
node = node.getLeftChild();
else if(comparator.compare(key, nodeKey) > 0)
node = node.getRightChild();
else {
isFound = true;
}
node = search(key, node);
}
if(isFound) return node;
else return null;
}
//Custom Methods
public boolean isEmpty() {
return rootNode == null;
}
private int height(Node n) {
return n == null ? -1 : n.getHeight();
}
private Node rotateWithLeftChild(Node node2) {
Node node1 = node2.left;
node2.left = node1.right;
node1.right = node2;
node2.height = Math.max(height(node2.left), height(node2.right)) + 1;
node1.height = Math.max(height(node1.left), node2.getHeight()) + 1;
return node1;
}
private Node rotateWithRightChild(Node node1) {
Node node2 = node1.right;
node1.right = node2.left;
node2.left = node1;
node1.height = Math.max(height(node1.left), height(node1.right)) + 1;
node2.height = Math.max(height(node2.left), node1.getHeight()) + 1;
return node2;
}
private Node doubleRotateWithLeft(Node node) {
node.left = rotateWithRightChild(node.left);
return rotateWithLeftChild(node);
}
private Node doubleRotateWithRight(Node node) {
node.right = rotateWithLeftChild(node.right);
return rotateWithRightChild(node);
}
}
Here is how I test the class:
package cw.avl;
import cw.util.AVLTree;
public class AVLTest
{
public static void main(String[] args) {
AVLTree<String, Integer> tree = new AVLTree<String, Integer>(String.CASE_INSENSITIVE_ORDER);
for (int i=1; i <= 10;i++) {
String s = "S" + i;
int x = i;
tree.insert(s, x);
tree.insert(s, x);
}
}
}
Well, you don't seem to ever assign to rootNode, so it starts null and remains so. In fact, your methods create nodes and return them:
if(node == null)
node = new Node(key, values);
...
return node
But you don't use the returned node.
Edit: longer explanation:
When you call from the other function like this: Node n = insert(key, value, rootNode); you are basically saying: Node n = insert(key, value, null);. On the receiving end, here:
public Node insert(K key, V value, Node node) { ,
you are creating a new variable called node with initial value null. Then you replace that value when you do:
node = new Node(key, values);
That value is for the node variable in the insert(K,V,N) method, in no way is rootNode retroactively updated. You could just do so right there:
if(node == null) {
node = new Node(key, values);
rootNode = node;
}
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.