I'm attempting to write a pre-order traversal algorithm on a binary tree using the recursive method. Here's what I have:
void traverse(BT t) {
if (t == null){
return;
}
System.out.print(t);
traverse(t.left);
traverse(t.right);
}
That doesn't compile for some reason. I think the problem is with the rest of my code. Here's the entire code:
class ZOrep extends TreeAndRepresentation {
private int k;
ZOrep left;
ZOrep right;
ZOrep( int m, int[] b ) { // given sequence build tree
super( m, b );
N = (M-1)/2;
k = -1;
t = build();
}
ZOrep( int n, BT t ) { // given tree build sequence
super(n, t);
t = build();
traverse( t );
}
BT build() {
return(a[++k] == 0 ? null : new BT( build(), build() ));
}
void traverse(BT t) {
if (t == null){
return;
}
System.out.print(t);
traverse(t.left);
traverse(t.right);
}
}
I feel like I'm missing something when I'm building the tree (with my ZOrep method). Also here's the BT class:
class BT {
BT L; BT R;
BT( BT l, BT r ) { L = l; R = r; }
}
Currently my compiler says it can't find the symbol for t.left and t.right.
When the compiler says it can't find the symbol, it means the field you're trying to reference doesn't exist.
Looking at your class BT, this is correct; BT doesn't have left or right, it has L and R. Thus, replacing
traverse(t.left);
traverse(t.right);
with
traverse(t.L);
traverse(t.R);
Will fix this issue.
Currently my compiler says it can't find the symbol for t.left and t.right.
This is because t is a BT and it doesn't have a left and a right.
I suggest you decide what you want to call your tree node class. Is it ZOrep or BT and only use one of these or you will create confusion.
System.out.print(t);
If you want to print out a BT, you will need to add a toString() method to it as the default won't tell you anything useful.
What are you passing into your transverse function? If it's a BT object, then you can't use left and right, you must use L and R. Left and right are parts of your object that extends from BT, but it looks like you're passing in a BT.
// Java
static String tree = "";
private static void preOrder(HuffTree currentObject) {
if (currentObject == null) {
return;
}
if (currentObject.filling == null) tree += 1;
else tree += 0;
preOrder(currentObject.child0);
preOrder(currentObject.child1);
}
}
// class code here
import java.util.Objects;
/**
Huffman tree as class
*/
class HuffTree implements Comparable {
// element filling
Byte filling;
// element repeats
int repeats;
// zero child
HuffTree child0;
// child 1
HuffTree child1;
/**
* constructor for tree fathers and leaves
*/
public HuffTree(Byte filling, int repeats, HuffTree child0, HuffTree child1) {
// father filling
this.filling = filling;
// father repeats
this.repeats = repeats;
// zero child
this.child0 = child0;
// child 1
this.child1 = child1;
}
/**
* finding difference between our tree's items
*/
#Override
public int compareTo(HuffTree currentByte) {
return currentByte.repeats - repeats;
}
/**
* take byte code as a string by recursive three search in depth
*/
public String getCodeForByte(Byte currentByte, String wayToFather) {
// there is 4 cases:
if (!Objects.equals(filling, currentByte)) {
// case 1 - zero child found
if (child0 != null) {
// recursive code add for zero child
String currentWay = child0.getCodeForByte(currentByte, wayToFather + "0");
// return temporary string
if (currentWay != null) return currentWay;
}
// case 2 - child 1 found. recursive code add for child 1. return temporary string
if (child1 != null) return child1.getCodeForByte(currentByte, wayToFather + "1");
}
// case 3 - correct leaf found. return correct code
if (Objects.equals(filling, currentByte)) return wayToFather;
// case 4 - wrong leaf found. return null
return null;
}
}
Related
I am creating a program that inserts a character (number/letter) into a binary tree. So far, I'm able to produce an output but it's not what I expected. These are the problems I'm encountering:
The insert method is not able to print the correct height of the tree. I am not sure where I should insert my height++; statement to get the correct output.
The insert method is only able to add nodes to the right.
Expected Output: ht=3 [K=3 L=[K=1 R=[K=2]] R=[K=5 L=[K=4]]]
My Output: ht=4 [K=3 R=[K=1 R=[K=2 R=[K=5 R=[K=4]]]]
(all nodes are only added to the right 'R')
Here are my classes for reference:
Main Class
BST<Character> bst = new BST<>();
bst.insert('3');
bst.insert('1');
bst.insert('2');
bst.insert('5');
bst.insert('4');
System.out.println("ht=" + bst.height + " " + bst.toString());
BST Class - where the insert method is declared
public class BST<T> extends BT<T> {
// insert() method
public void insert(char k)
{
if (root == null) {
root = new BTNode(k);
return;
}
BTNode<T> n = root;
BTNode<T> p = null; // parent
while (n != null) {
p = n;
if (k < n.value) {
n = n.left;
} else {
n = n.right;
}
}
if (k < p.value) {
p.left = new BTNode(k);
} else {
p.right = new BTNode(k);
height++; // adds 1 to height when a new level is made
}
}
}
BTNode Class
public class BTNode<T> {
T info;
int value, level;
BTNode<T> left, right;
public BTNode(T el) {
this(el, null, null);
}
public BTNode(T el, BTNode<T> l, BTNode<T> r) {
info = el;
left = l;
right = r;
}
}
BT Class - where the toString method is declared
public class BT<T> {
BTNode<T> root = null;
int height = 0;
public BT() {
BTNode<T> node = new BTNode("");
}
// other methods
// toString()
public String toString() {
return toString(root);
}
public String toString(BTNode<T> n) {
String s = "";
if (n == null) {
return "";
}
if (n != null) {
s = "[K=" + n.info;
if (n.left != null) {
s = s + " L=" + toString(n.left) + "]";
}
if (n.right != null) {
s = s + " R=" + toString(n.right) + "]";
}
}
return s;
}
}
Hope you can help me out, thanks!
You have quite a few issues in your code. I'll list a few immediate items but you really will need to learn to use an interactive debugger and unit testing to resolve the sorts of issues you are seeing.
You refer to the value field in BTNode in your comparison but it is never set. You should really be referring to info (which is the actual data in the node).
But given info is a generic type you can't use standard comparison operators. Instead you'll need to define it as <T extends Comparable<T>> and then use n.info.compareTo(k) > 0.
The key passed into insert should also be of type T
Which means the other classes also need to ensure T extends Comparable.
Height is only incremented when nodes are added to the right which makes no sense.
Height needs to be increased only when a node is inserted further from the root than the current maximum. Something like the following:
int depth = 0;
while (n != null) {
depth++;
p = n;
...
}
depth++;
if (depth > height)
height = depth;
You should get used to making your fields private and accessing them through getters. In your case a compareValue method would likely make sense.
I am trying to create a binary tree that takes strings but it uses "-" and "+" to go left or right if the sign is + insert left and if it's - then insert right. Here is a visual representation of what I am trying to do.
insert method should take the word and just a single sign for now and based of that insert right or left
Here is my code but I am getting nullpointer error. Apparently, I am not inserting into the right order
public class BinaryTree {
private static Node root = null;
private static Node sign = null;
public static void main(String[] args) {
// TODO Auto-generated method stub
BinaryTree bt = new BinaryTree();
bt.insert("to", "-");
bt.insert("the", "+");
bt.preorder();
}
private class Node {
String data;
String sign;
Node left;
Node right;
public Node(String w) {
data = w;
left = right = null;
}
// public Node(String w, String s) {
// data = w;
// sign = s;
// left = right = null;
//
// }
} // -----------------end of Node
private void insert(String val, String sign) {
root = insert(root, val, sign);
}
Node insert(Node r, String data, String passSign) {
if (r == null) {
return new Node(data);
}
if(r.sign.equals(passSign)) {
r.right = insert(r.right, data, passSign);
}
else if (r.sign.equals(passSign)){
r.left = insert(r.left, data, passSign);
}
return r;
}
public void preorder() {
preorder(root);
}
public void preorder(Node p) {
if (p != null) {
System.out.println(p.data);
preorder(p.left);
preorder(p.right);
}
}
}
The main problems are:
The BinaryTree nor the Node instances should have a sign member. The sign only plays a role during the insertion process, but has no meaning any more once a node is inserted
r.sign.equals(passSign) is therefore also not the correct condition to check. According to your description you should just check whether the sign is a "-" and go right, or else go left ("+"). There is no state of the node that influences this decision. So do passSign.charAt(0) == '-' instead.
When making the recursive call you should not pass the same sign again: it has already been processed. Instead, pass any signs that follow after the consumed one. You can use substring for that purpose.
The image shows a root node that has no value. Yet you are right in creating a tree instance with no node at all. So your insert method should deal with the case where the root is null, but the sign argument is not the empty string. In that case a root node should be created, but it should not hold the target data, as for that we should still go deeper in the tree. This principle could apply to any node, not only the root. So foresee the creation of such "place-holder" nodes and give them some default value (like "(null)").
Not a problem, but I find it more useful to print in inorder order, and indent the deeper nodes. This way you get an idea how the tree is structured.
Here is the corrected code:
public class BinaryTree {
private static Node root = null;
// No sign member needed;
public static void main(String[] args) {
BinaryTree bt = new BinaryTree();
bt.insert("to", "-");
bt.insert("the", "+");
bt.insert("buy", "-+");
bt.insert("imperial", "+-");
bt.insert("afflication", "++");
bt.inorder();
}
private class Node {
String data;
// No sign member needed;
Node left;
Node right;
public Node(String w) {
data = w;
left = right = null;
}
}
private void insert(String val, String sign) {
root = insert(root, val, sign);
}
Node insert(Node r, String data, String passSign) {
// Check whether there is a sign
if (passSign.length() == 0) {
return new Node(data);
}
// If needed, create a placeholder node so to be able to descend further
if (r == null) {
r = new Node("(null)");
}
if (passSign.charAt(0) == '-') {
// Extract the rest of the signs
r.right = insert(r.right, data, passSign.substring(1, passSign.length()));
}
else {
r.left = insert(r.left, data, passSign.substring(1, passSign.length()));
}
return r;
}
public void inorder() {
inorder(root, "");
}
// This method gives a bit more visual output
public void inorder(Node p, String indent) {
if (p != null) {
inorder(p.left, indent + " ");
System.out.println(indent + p.data);
inorder(p.right, indent + " ");
}
}
}
I'm trying to write a Huffman-tree decode function to decode a given Boolean array.I'm using the recursion method in the decode_helper() but I keep getting caught in an infinite loop, and I'm not sure as to why because I thought I implemented a proper base case to stop the recursive calls.
I've tried playing around with different base cases but nothing that I try seems to stop the recursive calls.
public class HuffmanTree {
public class HuffmanTree {
// ******************** Start of Stub Code ******************** //
// ************************************************************ //
/** Node<E> is an inner class and it is abstract.
* There will be two kinds
* of Node, one for leaves and one for internal nodes. */
abstract static class Node implements Comparable<Node>{
/** The frequency of all the items below this node */
protected int frequency;
public Node(int freq) {
this.frequency = freq;
}
/** Needed for the Minimum Heap used later in this stub. */
public int compareTo(Node other) {
return this.frequency - other.frequency;
}
}
/** Leaves of a Huffman tree contain the data items */
protected static class LeafNode extends Node {
// Data Fields
/** The data in the node */
protected char data;
/** Constructor to create a leaf node (i.e. no children) */
public LeafNode(char data, int freq) {
super(freq);
this.data = data;
}
/** toString method */
public String toString() {
return "[value= "+this.data + ",freq= "+frequency+"]";
}
}
/** Internal nodes contain no data,
* just references to left and right subtrees */
protected static class InternalNode extends Node {
/** A reference to the left child */
protected Node left;
/** A reference to the right child */
protected Node right;
/** Constructor to create an internal node */
public InternalNode(Node leftC, Node rightC) {
super(leftC.frequency + rightC.frequency);
left = leftC; right = rightC;
}
public String toString() {
return "(freq= "+frequency+")";
}
}
// Enough space to encode all "extended ascii" values
// This size is probably overkill (since many of the values are not
//"printable" in the usual sense)
private static final int codex_size = 256;
/* Data Fields for Huffman Tree */
private Node root;
public HuffmanTree(String s) {
root = buildHuffmanTree(s);
}
/**
* Returns the frequencies of all characters in s.
* #param s
* #return
*/
//How many times a character shows up in a string
public static int[] frequency(String s) {
int[] freq = new int[codex_size];
for (char c: s.toCharArray()) {
freq[c]++;
}
return freq;
}
public String decode(boolean[] coding) {
// TODO Complete decode method
//Function to decode the binary input
String code = "";
Node temp = root;
int i = 0;
if (coding.length == 0) {
throw new IllegalArgumentException("The given code cannot be empty");
}
for(int j = 0; j < coding.length; j++) {
if(coding[j] != true && coding[j] != false) {
throw new IllegalArgumentException("The given code has an invalid
input");
}
}
decode_helper(temp, code, coding);
return code;
}
public void decode_helper(Node root, String code, boolean[] coding) {
int i = 0;
if(root == null) {
throw new IllegalArgumentException("Given tree is empty");
}
//Base case for the recursion
if(i != coding.length) {
if (root instanceof InternalNode) {
InternalNode n = (InternalNode)root;
if(coding[i] == false) {
n.left = (InternalNode)root;
i++;
decode_helper(n.left, code, coding);
}
if(coding[i] == true) {
n.right = (InternalNode)root;
i++;
decode_helper(n.right, code, coding);
}
}
else if (root instanceof LeafNode) {
LeafNode l = (LeafNode)root;
code += l.data;
i++;
decode_helper(root, code, coding);
}
}
}
The issue is because you are initializing int i = 0 within the decode_helper method. And that method is called recursively. Since i is always initialized to zero, it would never become equal to coding.length and hence the infinite loop.
You might need to initialize i outside the decode_helper method and pass it inside it.
I am currently writing a method that removes a given value from a binary search tree. However when I call it, it deletes the said value but then duplicates every other value. I have no idea why. Please tell me what is wrong.
There are two methods, one that find the elements, and the other that deletes it.
Here is the one that finds that element...
public static TreeNode delete(TreeNode t, Comparable x, TreeDisplay display)
{
if( x.compareTo(t.getValue()) > 0)
{
display.visit(t);
t.setRight(delete( t.getRight(), x, display));
}
else if ( x.compareTo(t.getValue()) < 0)
{
display.visit(t);
t.setLeft(delete(t.getLeft(), x, display));
}
else
{
t = deleteNode(t, display);
}
return t;
This is the method that deletes the value
private static TreeNode deleteNode(TreeNode t, TreeDisplay display)
{
if (t.getRight()!=null)
{
TreeNode right = t.getRight();
TreeNode max = (TreeNode)TreeUtil.leftmost(right);
TreeNode previous = null;
while ( right.getLeft()!=null&&right.getLeft().getLeft()!=null)
{
right = right.getLeft();
}
t.setValue(max.getValue());
if ( max.getRight()==null)
{
right.setLeft(null);
}
else
{
right.setLeft(max.getRight());
}
}
else if (t.getLeft() !=null)
{
TreeNode left = t.getLeft();
TreeNode max = (TreeNode)TreeUtil.rightmost(left);
while(left.getRight()!=null &&left.getRight().getRight()!=null)
{
left = left.getRight();
}
t.setValue(max.getValue());
if ( max.getLeft()==null)
{
left.setRight(null);
}
else
{
left.setRight(max.getLeft());
}
}
else
{
t = null;
}
return t;
}
Thanks in advance!
...it deletes the said value but then duplicates every other value. I have no idea why. Please tell me what is wrong.
It's because you're returning the deleted node from deleteNode(), and in the first method delete(), your calls to setRight() and setLeft() are setting every traversed element to the deleted element as the recursion unwinds back up the tree.
Given a generic tree implemented as a root node with a list of sons, which sons are nodes and again each node has a list of its sons.
__A__
/ | \
B C D
| / \
E F G
The node A has a list of its sons: B, C, D
B, C, D also have a list of their sons: B --> E ; C --> F, G ; D --> null ;
I will explain my idea of the algorithm, you can fix it or give me another completely new idea.
public Integer level(T dato) {...}
Traverse the tree adding to the queue each node of the tree or adding a "null" if the last node added is the last node of the level. Null is an identifier in the queue to know where the level has ended.
My problem is that I don't know exactly where to put the identifier after the first time.
Here is some of the code:
public Integer level(T data){
int inclu= this.include(data);
if (inclu==-1) { // if the tree doesn't include the data
return -1;
} else {
return inclu; // returns the level
}
}
public Integer include( T data ) { // returns the level where the data is
Integer inclu = -1; // -1 if the data is not included
if (this.getDataRoot()==data){
return 0; // The root of the tree has the data
}
else {
LinkedList<GenericNode<T>> queue = new LinkedList<GenericNode<T>>();
GenericNode<T> tree = new GenericNode<T>();
int level=1;
queue.addAtBeginning(this.getRoot());
queue.addAtBeginning(null);
while (queue.size()>0 && inclu==-1) {
if(queue.element(queue.size())!=null) { // if it is not the end of the level then dequeue
tree.setData(queue.element(queue.size()).getData()); //queue.element(position) returns the element in that position
tree.setListOfSons(queue.element(queue.size()).getSons());
if (tree.getSons()!=null) { // if the tree has sons
int i=1;
while(i<=tree.getSons().size() && inclu==-1) {
queue.addAtBeginning(tree.getSons().element(i));
if (tree.getSons().element(i).getData()==data) // if I found the data I'm looking for
inclu=level;
i++; // counter
}
}
} else { // if it is the end of the level (means the queue gave me a null)
level++;
}
queue.delete(queue.size()); //ending the dequeue process
} //end while
} // end main else
return inclu; //returns the summation of the levels or 0 if it was found at the root of the tree or -1 if the data was not found
}
I wrote a class that returns the level of target node in specific tree.
import java.util.LinkedList;
import java.util.List;
public class TreeLevel {
public static class Node {
public Node(String data) { this.data = data ; };
public String data;
public List<Node> childs = new LinkedList<Node>();
}
public static Integer level(Node tree, Node target){
return level(tree, target, 0);
}
private static Integer level(Node tree, Node target, int currentLevel) {
Integer returnLevel = -1;
if(tree.data.equals(target.data)) {
returnLevel = currentLevel;
} else {
for(Node child : tree.childs) {
if((returnLevel = level(child, target, currentLevel + 1)) != -1){
break;
}
}
}
return returnLevel;
}
public static void main(String[] args) {
Node a = new Node("A");
Node b = new Node("B");
Node c = new Node("C");
Node d = new Node("D");
Node e = new Node("E");
Node f = new Node("F");
Node g = new Node("G");
// childs of a:
a.childs.add(b);
a.childs.add(c);
a.childs.add(d);
// childs of b:
b.childs.add(e);
// childs of c:
c.childs.add(f);
c.childs.add(g);
// childs of d:
// d.childs = null or simply d.childs.length() is 0
Node target = new Node("G");
Integer level = level(a, target);
System.out.println("level [" + level + "]");
}
}
I think I can give you a simple code for this question. You can change the it according to your code.
public Integer include( T data ) { // returns the level where the data is
Integer inclu = -1; // -1 if the data is not included
if (this.getDataRoot() == data){
return 0; // The root of the tree has the data
}
return level(this.getRoot(), data, 1);
}
//Find data in a tree whose root is Node
//If not found, return -1
public int level(T node, T data, int level) {
if (!node.hasChildren()) {
return -1;
}
for (T child : node.getChildren()) {
if (child.getData == data) {
return level; //Aha!!! found it
} else {
int l = level(child, data, level + 1); /// find in this sub-tree
if (l != -1) {
return l;
}
}
}
return -1; /// Not found in this sub-tree.
}
P.S : == is used to compare, which is not good. .equals() should be used.