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);
}
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);
}
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.
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.
I'm trying to create a method to remove nodes from a Binary Tree but I am having a problem, it seems to be ok but I have another method for printing all of them and after "deleting" a specific node I use the print method but it prints all of them including the one I've already deleted.
public class BinaryTree
{
Node root;
Node n;
private class Node
{
public Node f; //father
public Node right;
public Node left;
public int key; // key
public String Student;
public int Mark;
public Node(int key)
{
right = null;
left = null;
f = null;
Student = null;
Mark = 0;
}
}
public void remove()
{
System.out.println("");
System.out.println("Which student do you want to delete? Write down his ID.");
int id = Genio.getInteger();
n = new Node(id);
Node temporal = root;
if(root == null)
{
System.out.println("This tree is empty");
}
else
{
while(temporal != null)
{
n.f = temporal;
if(n.key == temporal.key)
{
if(n.f.right == null && n.f.left == null)
{
n = null;
temporal = null;
}
}
else if(n.key >= temporal.key)
{
temporal = temporal.right;
}
else
{
temporal = temporal.left;
}
}
}
}
}
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.