I'm new in Java. I'm trying to obtain the height of my tree and the depth of every node in a huffman tree.
I have been trying different method to obtain the height but it's still not working.
I can't figure out whats the problem.
Right now I'm getting an error:
Exception in thread "main" java.lang.ClassCastException: HuffmanLeaf cannot be cast to HuffmanNode
at HuffmanCode.findHeight(HuffmanCode.java:95)
at HuffmanCode.printResults(HuffmanCode.java:71)
at Main.main(Main.java:31)
Please, I'm stuck on that.
import java.util.*;
public class HuffmanCode {
int numberOfNode = 1;
int height;
String fullcode = "";
String realcode = "";
// input is an array of frequencies, indexed by character code
public HuffmanTree createTree(int[] charFreqs) {
PriorityQueue<HuffmanTree> trees = new PriorityQueue<HuffmanTree>();
// initially, we have a forest of leaves
// one for each non-empty character
for (int x = 0; x < charFreqs.length; x++) {
if (charFreqs[x] > 0)
/*
* My first step of Huffman coding Create a leaf node for each
* character and add it to the priority queue with the offer
* method
*/
trees.offer(new HuffmanLeaf(charFreqs[x], (char) x));
}
while (trees.size() > 1) {
// Poll the two nodes with least frequency
HuffmanTree a = trees.poll();
HuffmanTree b = trees.poll();
// put into new node and re-insert into queue
trees.offer(new HuffmanNode(a, b));
numberOfNode++;
}
return trees.poll();
}
public void printResults(HuffmanTree tree, StringBuffer prefix) {
// assert tree != null;
if (tree instanceof HuffmanLeaf) {
HuffmanLeaf leaf = (HuffmanLeaf) tree;
System.out.println(leaf.value + "\t" + leaf.frequency + "\t" + prefix);
encodedInput(prefix);
for (int x = 0; x < leaf.frequency; x++) {
realcode = realcode + prefix;
}
} else if (tree instanceof HuffmanNode) {
HuffmanNode node = (HuffmanNode) tree;
numberOfNode++;
// move left
prefix.append('0');
printResults(node.left, prefix);
prefix.deleteCharAt(prefix.length() - 1);
findHeight(node);
// move right
prefix.append('1');
printResults(node.right, prefix);
prefix.deleteCharAt(prefix.length() - 1);
height = findHeight(node);
}
}
public void encodedInput(StringBuffer prefix) {
fullcode = fullcode + " , " + prefix;
}
//Method to get height
public int findHeight(HuffmanNode node) {
if (node == null) {
return -1;
}
int lefth = findHeight((HuffmanNode) node.left);
int righth = findHeight((HuffmanNode) node.right);
if (lefth > righth) {
return lefth + 1;
} else {
return righth + 1;
}
}
}
Other class I have:
class HuffmanNode extends HuffmanTree {
public HuffmanTree left;
public HuffmanTree right;
public HuffmanNode(HuffmanTree left, HuffmanTree right) {
super(left.frequency + right.frequency);
this.left = left;
this.right = right;
}
}
class HuffmanLeaf extends HuffmanTree {
public char value; // the character this leaf represents
public HuffmanLeaf(int frequency, char value) {
super(frequency);
this.value = value;
}
}
public class HuffmanTree implements Comparable<HuffmanTree> {
public int frequency; // the frequency of this tree
public HuffmanTree(int frequency) {
this.frequency = frequency;
}
public int compareTo(HuffmanTree tree) {
return frequency - tree.frequency;
}
}
You are doing
trees.offer(new HuffmanLeaf(charFreqs[x], (char) x));
and afterwards, you do:
HuffmanTree a = trees.poll();
HuffmanTree b = trees.poll();
// put into new node and re-insert into queue
trees.offer(new HuffmanNode(a, b));
So actually a or b might be instance of HuffmanLeaf
In that case,
(HuffmanNode) node.left
causes error since node.left is actually an instance of HuffmanLeaf
So here's the code that works.
// Method to get height
public int findHeight(HuffmanTree tree) {
if (tree == null) {
return -1;
}
if (tree instanceof HuffmanLeaf) {
return 1;
} else if (tree instanceof HuffmanNode) {
int lefth = findHeight(((HuffmanNode) tree).left);
int righth = findHeight(((HuffmanNode) tree).right);
if (lefth > righth) {
return lefth + 1;
} else {
return righth + 1;
}
} else {
return -1; // does not happen, you might want to raise exception.
}
}
You have to consider the both case when the actual instance of HuffmanTree is either HuffmanNode or HuffmanLeaf.
Related
I want to return number of values that is the most frequently in BinaryTree. I have BinaryClass which contain a lot of methods as add, contain, isEmpty, counter, iterator and other.I tried to implement this method public int getMaxFrequency() but I get a problem StackOverFlowException at markerd row.
When I run my code I get StackOverFlow Exception, anyone can help me please,
I'm new in BinaryTree.
Help me please.
enter code here
public class TreeSetCounter<T extends Comparable<T>> implements Iterable<T>{
public Node<T> root;
int size;
int count=0;
public TreeSetCounter() {
root = null;
size = 0;
}
public int counter(T t) {
return counterRecursive(root, t);
}
public int counterRecursive(Node<T> root, T t) {
int count = 0;
if(root == null) {
return 0;
}
if(root.value.equals(t)) {
count++;
}
count = count + counterRecursive(root.left, t)+ counterRecursive(root.right, t);
return count; }
public int getMaxFrequency(){
return inorder(root);
}
public int inorder( Node<T> prev) {
int count = 1, max = 0;
if (root == null) {
return 0;}
List<T> list = new ArrayList<>();
inorder(root.left); // I get the Exception att this row code.
while (prev != null) {
if (root.value == prev.value)
count++;
else
count = 1;
}
if (count > max) {
max = count;
list.clear();
list.add(root.value);
} else if (count == max) {
list.add(root.value);
}
prev = root;
inorder(root.right);
return max;
}
enter code here
Node.java
public class Node <T>{
T value;
int counter;
Node<T> left;
Node<T> right;
Node(T value, int count) {
this.value = value;
right = null;
left = null;
this.counter= count;
}
enter code here
public static void main(String[] args) {
TreeSetCounter <String> tsc= new TreeSetCounter<String>();
tsc.add("java");
tsc.add("java");
tsc.add("not");
tsc.add("cool");
tsc.add("java");
tsc.add("is");
tsc.add("java");
tsc.add("good");
System.out.println(tsc.getMaxFrequency());}
Try something like this for your counter functions:
public int counter (T t) {
if (root == null) return 0;
int count = 0;
if (root.value.equals(t))
count++;
count += counterRecursive(root.left, t);
count += counterRecursive(root.right, t);
return count;
}
public int counterRecursive (Node<T> root, T t) {
if (root == null) return 0;
if (root.value.equals(t))
return 1 + counterRecursive(root.left, t) + counterRecursive(root.right, t);
else
return counterRecursive(root.left, t) + counterRecursive(root.right, t);
}
The counter function looks like the main method to use, and counterRecursive is your helper function. More complex recursive solutions typically have this kind of design pattern.
Think in terms of Fibonacci:
public static int fibonacci (int n) {
return (n <= 1) ? n : fibonacci(n - 1) + fibonacci(n - 2);
}
This should help you debug inOrder and getMaxFrequency. I would use counter in getMaxFrequency while I look through the rest. Generally speaking, using a HashMap or HashTable is much more adequate for keeping track of counts.
Try something like this:
public int getMaxFrequency () {
if (root == null) return 0;
HashMap<T, Integer> counts = new HashMap<T, Integer>();
int count = counter(root.value);
counts.put(root.value, count);
// traverse the tree and grab counts
int left = getMaxFrequencyHelper(root.left, counts, count);
int right = getMaxFrequencyHelper(root.right, counts, count);
return left > right ? left : right;
}
private int getMaxFrequencyHelper (Node<T> node, HashMap<T, Integer> counts, max) {
if (node == null) return max;
if (!counts.containsKey(node.value))
counts.put(node.value, counter(node.value));
int _max = counts.get(node.value) > max ? counts.get(node.value) : max;
int left = getMaxFrequencyHelper(node.left, counts, _max);
int right = getMaxFrequencyHelper(node.right, counts, _max);
return left > right ? left : right;
}
This technique is called memoization where the previous counts are cached in a HashMap.
The question is to obtain median of given elements. If odd then simply return the middle element else return the mean of the n/2 and n/2 + 1 element.
The problem is that it is always returning 1 as the median, which probably means that rotation is not happening as 1 was my first input.
I know it is a famous leet code question, but i have written all my code by myself and there is no one else in the discussion panel whose code is written on avl tree from scratch.
Code:
'''
class Node{
int data;
Node left, right;
int height;
Node(int d){
this.data = d;
this.left = this.right = null;
this.height = 1;
}
Node(){
this.left = this.right = null;
}
}
class MedianFinder {
static Node root;
MedianFinder(){
root = new Node();
}
public void addNum(int num) {
insert(root, num);
}
public static Node insert(Node root, int num){
if(root == null)
return (new Node(num));
if(root.data < num){
root.right = insert(root.right, num);
}
else if(root.data > num)
root.left = insert(root.left, num);
root.height = max(height(root.left) , height(root.right)) + 1;
int balance = get_balance(root);
// if left left
if(balance > 2 && num < root.left.data){
return rightRotation(root);
}
// left right case
if(balance > 2 && num > root.left.data){
leftRotation(root.left);
return rightRotation(root);
}
// right right case
if(balance < -1 && num > root.right.data)
return leftRotation(root);
// right left case
if(balance < -1 && num < root.right.data){
rightRotation(root.right);
return leftRotation(root);
}
return root;
}
public static Node rightRotation(Node node){
Node temp = node.left;
Node tempright = temp.right;
temp.right = node;
node.left = tempright;
node.height = max(height(node.left), height(node.right)) + 1;
temp.height = max(height(temp.left), height(temp.right)) + 1;
return temp;
}
public static Node leftRotation(Node node){
Node temp = node.right;
Node templeft = temp.left;
temp.left = node;
node.right = templeft;
node.height = max(height(node.left), height(node.right)) + 1;
temp.height = max(height(temp.left), height(temp.right)) + 1;
return temp;
}
public static int get_balance(Node node){
if(node == null)
return 0;
return height(node.left) - height(node.right);
}
public static int height(Node node){
if(node == null)
return 0;
return node.height;
}
public static int max(int a, int b){
return a>b?a:b;
}
public double findMedian() {
if(height(root.left) == height(root.right))
return root.data;
return (root.data + root.right.data) / 2;
}
public static int count(Node node){
if(node == null)
return 0;
return 1 + count(node.left) + count(node.right);
}
}
/**
* Your MedianFinder object will be instantiated and called as such:
* MedianFinder obj = new MedianFinder();
* obj.addNum(num);
* double param_2 = obj.findMedian();
*/
'''
I am trying to implement a max priority queue using a heap binary tree with a triple-linked node. This is the code that I currently have yet when I run it and try to print out the tree nothing prints out it is just empty lines. I am using the helped methods sink and swim in order to help me organize the queue as I add different elements. I am also implementing an ADT (MaxPQ) which just has the public methods that need to be implemented. I was wondering if there is anything that I am doing wrong?
public class LinkedMaxPQ<T extends Comparable<T>> implements MaxPQ<T> {
// Instance variables
Node root;
int size;
Node lastInserted;
// Node inner class definition
// Node class
class Node {
int N;
T info;
Node left;
Node right;
Node parent;
Node(T info, int N) {
this.info = info; this.N = N;
}
}
private void swim(Node x){
if(x == null) return;
if(x.parent == null) return; // we're at root
int cmp = x.info.compareTo(x.parent.info);
if(cmp > 0){
swapNodeData(x, x.parent);
swim(x.parent);
}
}
private void swapNodeData(Node x, Node y){
T temp = x.info;
x.info = y.info;
y.info = temp;
}
private void sink(Node x){
if(x == null) return;
Node swapNode;
if(x.left == null && x.right == null){
return;
}
else if(x.left == null){
swapNode = x.right;
int cmp = x.info.compareTo(swapNode.info);
if(cmp < 0)
swapNodeData(swapNode, x);
} else if(x.right == null){
swapNode = x.left;
int cmp = x.info.compareTo(swapNode.info);
if(cmp < 0)
swapNodeData(swapNode, x);
} else{
int cmp = x.left.info.compareTo(x.right.info);
if(cmp >= 0){
swapNode = x.left;
} else{
swapNode = x.right;
}
int cmpParChild = x.info.compareTo(swapNode.info);
if(cmpParChild < 0) {
swapNodeData(swapNode, x);
sink(swapNode);
}
}
}
String printThisLevel (Node rootnode, int level) {
StringBuilder s = new StringBuilder();
// Base case 1: if the current rootnode is null, return the current string.
if (rootnode == null) {
return s.toString();
}
// Base case 2: If you're at the first level, append the
// info field of the current rootnode.
if (level == 1) {
s.append( rootnode.info.toString());
}
// Recursive calls: otherwise call the method on the left
// and on the right of the next lower level.
else if (level > 1) {
s.append( printThisLevel(rootnode.left, level-1));
s.append( printThisLevel(rootnode.right, level-1));
}
return s.toString();
}
private int size(Node x){
if(x == null) return 0;
return x.N;
}
private Node insert(Node x, T data){
if(x == null){
lastInserted = new Node(data, 1);
return lastInserted;
}
// compare left and right sizes see where to go
int leftSize = size(x.left);
int rightSize = size(x.right);
if(leftSize <= rightSize){
// go to left
Node inserted = insert(x.left, data);
x.left = inserted;
inserted.parent = x;
} else{
// go to right
Node inserted = insert(x.right, data);
x.right = inserted;
inserted.parent = x;
}
x.N = size(x.left) + size(x.right) + 1;
return x;
}
private Node resetLastInserted(Node x){
if(x == null) return null;
if(x.left == null && x.right == null) return x;
if(size(x.right) < size(x.left))return resetLastInserted(x.left);
else return resetLastInserted(x.right);
}
public void insert(T data){
root = insert(root, data);
swim(lastInserted);
}
public T getMax(){
if(root == null) return null;
return root.info;
}
public T removeMax(){
if(size() == 1){
T ret = root.info;
root = null;
return ret;
}
swapNodeData(root, lastInserted);
Node lastInsParent = lastInserted.parent;
T lastInsData = lastInserted.info;
if(lastInserted == lastInsParent.left){
lastInsParent.left = null;
} else{
lastInsParent.right = null;
}
Node traverser = lastInserted;
while(traverser != null){
traverser.N--;
traverser = traverser.parent;
}
lastInserted = resetLastInserted(root);
sink(root);
return lastInsData;
}
public int size(){
return size(root);
}
public boolean isEmpty(){
return size() == 0;
}
public String toString() {
// Create a StringBuilder object to make it more efficient.
StringBuilder sb=new StringBuilder();
// get the height of the tree
int height = (int)Math.ceil(Math.log(size+1) / Math.log(2));
// for each level in the tree, call printThisLevel and
// append the output to the StringBuilder
for (int i=1; i<=height; i++) {
sb.append("level " + i + ": "+ printThisLevel(this.root, i) + "\n");
}
// Return the string of the StringBuilder object
return sb.toString();
}
public static void main (String[] args) {
LinkedMaxPQ<String> t = new LinkedMaxPQ<String>();
t.insert("a");
System.out.println(t.toString());
t.insert("b");
t.insert("c");
t.insert("d");
t.insert("e");
t.insert("f");
t.insert("g");
t.insert("h");
t.insert("i");
t.insert("j");
t.insert("k");
t.size();
t.removeMax();
t.getMax();
t.removeMax();
t.insert("x");
t.insert("y");
t.removeMax();
t.getMax();
System.out.println(t.toString());
}
}
In this line:
int height = (int)Math.ceil(Math.log(size+1) / Math.log(2));
size should be size().
int height = (int)Math.ceil(Math.log(size()+1) / Math.log(2));
After this correction, the results are coming out.
However, there is a logic problem, which needs a solution.
For test case, testdata = new int[] {3, 5, 2, -7, 9, 4, 7};
The result is 9 4 7 -7 3 2 5
But correct result should be 9 5 7 -7 3 2 4 (from another array implementation).
I know the mistake comes from when at the 3rd levle, insert data {9}, its parent should be the 2nd leverl data {3} on the left, not the {2} on the right. Any thought to solve it?
I need to navigate my 23Tree and print all the levels and corresponding elements. However, my recursion goes in any one direction and does not return and perform other calls. Any help would be much appreciated.
Here is my node class:
class Node<T extends Comparable<T>> {
List<T> vals = new ArrayList<T>();
List<Node<T>> children = new ArrayList<Node<T>>();
boolean isLeaf() { return children.size() == 0; }
boolean is4Node() { return vals.size() == 3; }
// new Nodes always are 2-nodes (1 value). The node may be
// a leaf, or has 2 children.
Node(T x) {
vals.add(x);
}
Node(T x, Node<T> left, Node<T> right) {
vals.add(x);
children.add(left);
children.add(right);
children.add(null); // hack
}
This is my recursive function to print the nodes:
private boolean iterateChildrenAndPrintPerLevelAndLevelType(int level, String levelType, Node root){
System.out.println("present element: " + root);
if(root.vals.size() == 1 ){
System.out.println("Level = " + level + " [" + levelType + "] value = " + root.vals.get(0));
}else if(root.vals.size() == 2 ){
System.out.println("Level = " + level + " [" + levelType + "] value = " + root.vals.get(0) + "/" + root.vals.get(1));
}
if(root.children.get(0) != null){
iterateChildrenAndPrintPerLevelAndLevelType(level+1, "left", (Node) root.children.get(0));
}
if(root.children.get(1) != null){
iterateChildrenAndPrintPerLevelAndLevelType(level+1, "middle", (Node) root.children.get(1));
}
if(root.children.get(2) != null){
iterateChildrenAndPrintPerLevelAndLevelType(level+1, "right", (Node) root.children.get(2));
}
return true;
}
And here is the output:
present element: [[[a]b[c]]d, [[e]f[g]]h[[i]j, [k]y[z]]]
Level = 0 [root] value = d/h
present element: [[a]b[c]]
Level = 1 [left] value = b
present element: [a]
Level = 2 [left] value = a
(Edit) Here is my main method:
public static void main(String[] args) {
StringTwoThreeTree set = new StringTwoThreeTree();
try{
String line = null;
FileReader fileReader =
new FileReader("C:\\Users\\Redoubt\\IdeaProjects\\23Tree\\src\\resources\\test.dat");
// new FileReader("C:\\Users\\Redoubt\\IdeaProjects\\23Tree\\src\\resources\\a4q1search.txt");
// Always wrap FileReader in BufferedReader.
BufferedReader bufferedReader =
new BufferedReader(fileReader);
while((line = bufferedReader.readLine()) != null) {
set.insert(line);
}
// System.out.println("\n\n\n");
String str = set.toString();
// System.out.println(str);
set.print();
}catch (Exception e){
}
}
and the contents of the file test.dat :
a
a
b
c
d
e
f
g
h
i
j
k
y
z
Just for clarity, I'm adding the 2 large classes as well:
StringTwoThree class:
import java.util.List;
public class StringTwoThreeTree extends TwoThreeTree<String> {
#Override
public String toString() {
return super.toString();
}
public void insert(String str){
super.add(str);
}
public void print(){
Node root = super.root;
// System.out.println(root.vals);
// dumpList("",root);
iterateChildrenAndPrintPerLevelAndLevelType(0, "root", root);
super.displayLevelWise();
}
private void dumpList(String string, Node list) {
int i = 0;
for (Object item : list.children) {
if (item instanceof List) {
dumpList(string + i, (Node) item);
} else {
System.out.println(String.format("%s%d %s", string, i, item));
}
++i;
}
}
private boolean iterateChildrenAndPrintPerLevelAndLevelType(int level, String levelType, Node root){
System.out.println("present element: " + root);
if(root.vals.size() == 1 ){
System.out.println("Level = " + level + " [" + levelType + "] value = " + root.vals.get(0));
}else if(root.vals.size() == 2 ){
System.out.println("Level = " + level + " [" + levelType + "] value = " + root.vals.get(0) + "/" + root.vals.get(1));
}
if(root.children.get(0) != null){
iterateChildrenAndPrintPerLevelAndLevelType(level+1, "left", (Node) root.children.get(0));
}
if(root.children.get(1) != null){
iterateChildrenAndPrintPerLevelAndLevelType(level+1, "middle", (Node) root.children.get(1));
}
if(root.children.get(2) != null){
iterateChildrenAndPrintPerLevelAndLevelType(level+1, "right", (Node) root.children.get(2));
}
return true;
}
}
TwoThreeTree class:
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Queue;
public class TwoThreeTree<T extends Comparable<T>> implements Iterable<T> {
// a Node has 1 (2-Node) or 2 (3-Node) values
// and 2 or 3 children. Values and children are stored
// in ArrayLists. If there are children, that ArrayList
// has a null element at the end, so as to make easier the
// method which adds a new child.
class Node<T extends Comparable<T>> {
List<T> vals = new ArrayList<T>();
List<Node<T>> children = new ArrayList<Node<T>>();
boolean isLeaf() { return children.size() == 0; }
boolean is4Node() { return vals.size() == 3; }
// new Nodes always are 2-nodes (1 value). The node may be
// a leaf, or has 2 children.
Node(T x) {
vals.add(x);
}
Node(T x, Node<T> left, Node<T> right) {
vals.add(x);
children.add(left);
children.add(right);
children.add(null); // hack
}
public String toString() {
String answer = "[";
for (int i=0; i<vals.size(); i++) {
if (i != 0) answer += ", ";
if (children.size() != 0)
answer += children.get(i).toString();
answer += vals.get(i);
}
if (children.size() != 0)
answer += children.get(children.size()-2).toString();
return answer + "]";
}
// used in Iterator
void getVals(List<T> iteratorList) {
for (int i=0; i<vals.size(); i++) {
if (children.size() != 0)
children.get(i).getVals(iteratorList);
iteratorList.add(vals.get(i));
}
if (children.size() != 0)
children.get(children.size()-2).getVals(iteratorList);
}
// recursively adds a new value to a subtree
boolean add(T val) {
if (isLeaf())
return addToLeaf(val);
else return addToInterior(val);
}
// new values are always added to a leaf. The result may be a 4-node leaf.
boolean addToLeaf(T x) {
int cmp;
// size is 1 for a 2-node, or 2 for a 3-node
for (int i = 0; i < vals.size(); i++) {
cmp = x.compareTo(vals.get(i));
if (cmp == 0) return false;
else if (cmp < 0) {
vals.add(i,x);
return true;
}
}
vals.add(x);
return true;
}
// adds a value to a subtree rooted by an interior node. If
// the addition results in one of the children being a 4-node,
// then adjustments are made.
boolean addToInterior(T x) {
int cmp;
// size is 1 for a 2-node, or 2 for a 3-node
for (int i = 0; i <= vals.size(); i++) {
if (i == vals.size()) cmp = -1; // hack because there is no vals[2]
else cmp = x.compareTo(vals.get(i));
if (cmp == 0) return false;
else if (cmp < 0) {
boolean retVal = children.get(i).add(x);
if (children.get(i).is4Node())
childIs4Node(i);
return retVal;
}
}
return false; // unreachable -- just for compiler
}
// the ith child is a 4-node
void childIs4Node(int i) {
Node<T> the4Node = children.get(i);
// move the middle value from the 4-node child up
// to its parent
if (i == 2)
vals.add(children.get(i).vals.get(1));
else vals.add(i, children.get(i).vals.get(1));
Node<T> newChild1, newChild2;
if (children.get(i).isLeaf()) {
newChild1 = new Node<T>(children.get(i).vals.get(0));
newChild2 = new Node<T>(children.get(i).vals.get(2));
}
else {
newChild1 = new Node<T>(children.get(i).vals.get(0),
children.get(i).children.get(0),
children.get(i).children.get(1));
newChild2 = new Node<T>(children.get(i).vals.get(2),
children.get(i).children.get(2),
children.get(i).children.get(3));
}
children.remove(the4Node);
children.add(i, newChild2);
children.add(i, newChild1);
}
}
Node<T> root;
public TwoThreeTree() {
root = null;
}
// TwoThreeTree add
public boolean add(T val) {
if (root == null) {
root = new Node<T>(val);
return true;
}
else {
boolean isNew = root.add(val);
// if root is a 4-node, split it
if (root.vals.size() == 3) {
Node<T> left, right;
if (root.isLeaf()) {
left = new Node<T>(root.vals.get(0));
right = new Node<T>(root.vals.get(2));
}
else {
left = new Node<T>(root.vals.get(0),
root.children.get(0),
root.children.get(1));
right = new Node<T>(root.vals.get(2),
root.children.get(2),
root.children.get(3));
}
root = new Node<T>(root.vals.get(1), left, right);
}
return isNew;
}
}
// this method creates a list containing all of the values in
// the tree and returns that list's iterator
public Iterator<T> iterator() {
List<T> vals = new ArrayList<T>();
if (root != null) root.getVals(vals);
return vals.iterator();
}
public String toString(){
String result = "[";
for (T item : this
) {
result += item.toString() + ",";
}
result = result.substring(0,result.length()-1);
result += "]";
return result;
}
public void displayLevelWise(){
}
}
Your index is going out of bound in your private boolean iterateChildrenAndPrintPerLevelAndLevelType(int level, String levelType, Node root) method.
I know how to find if a binary tree has a certain path with a given sum (If this is not the best way please let me know):
int pathSum(MyNode root, int sum)
{
if(root == null)
return -1;
int temp = sum - root.value;
return(pathSum(root.left,temp) || pathSum(root.right,temp));
}
What I am not able to figure out is how to print the particular path.
My Node class looks like this:
class MyNode {
int value;
MyNode left;
MyNode right;
MyNode(int value)
{
this.value = value;
}
}
Try this, use overloading:
public void pathToSum(int sum) {
pathToSum(root, sum);
}
private boolean pathToSum(Node n, int sum) {
if (null != n) {
sum -= n.data;
boolean found = pathToSum(n.left, sum);
if (!found) {
found = pathtoSum(n.right, sum);
}
if (found) {
println(n.data);
return found;
}
}
return 0 == sum ? true : false;
}
This code is tested with the following classes:
import java.util.LinkedList;
import java.util.Queue;
public class BST {
Node root;
public BST(){
root = null;
}
public void insert(int el){
Node tmp = root, p=null;
while(null!=tmp && el != tmp.data){
p=tmp;
if(el<tmp.data)
tmp=tmp.left;
else
tmp=tmp.right;
}
if(tmp == null){
if(null == p)
root = new Node(el);
else if(el <p.data)
p.left= new Node(el);
else
p.right=new Node(el);
}
}//
public void pathToSum(int sum) {
pathToSum(root, sum);
}//
private boolean pathToSum(Node n, int sum) {
if (null != n) {
sum -= n.data;
boolean found = pathToSum(n.left, sum);
if (!found) {
found = pathToSum(n.right, sum);
}
if (found) {
System.out.println(n.data);
return found;
}
}
return 0 == sum ? true : false;
}
public static void main(String[] args){
int[] input={50,25,75,10,35,60,100,5,20,30,45,55,70,90,102};
BST bst = new BST();
for(int i:input)
bst.insert(i);
bst.pathToSum(155);
}
}
class Node{
public int data;
public Node left;
public Node right;
public Node(int el){
data = el;
}
}
Result:
45
35
25
50
I suggest to alter your MyNode class to include a parent node:
MyNode left;
MyNode right;
MyNode parent;
MyNode(int value, MyNode parent)
{
this.value = value;
this.parent = parent;
}
and then when you hit a node with correct sum, you can pass that node to another function that goes throug the ancestry until it hits node with null parent (the root).
Nice puzzle, I liked it. You almost had it, just some confusion over int vs boolean, and not checking end condition of sum being zero.
public class NodeSums {
static boolean pathSum(MyNode root, int sum) {
boolean ret;
if (root == null) {
ret = sum == 0;
} else {
int remain = sum - root.value;
ret = pathSum(root.left,remain) || pathSum(root.right, remain);
}
return ret;
}
static class MyNode {
int value;
MyNode left;
MyNode right;
MyNode(int value) {
this.value = value;
}
}
public static void main(String[] args) {
/**
* Valid sums will be 3, 8, and 9
*
* 1 -- 2
* --
* -- 3 -- 4
* --
* -- 5
*/
MyNode root = new MyNode(1);
root.left = new MyNode(2);
root.right = new MyNode(3);
root.right.left = new MyNode(4);
root.right.right = new MyNode(5);
for (int i = 1; i < 10; i++) {
System.out.println("Path sum " + i + " " + pathSum(root, i));
}
}
}
Output
Path sum 1 false
Path sum 2 false
Path sum 3 true
Path sum 4 false
Path sum 5 false
Path sum 6 false
Path sum 7 false
Path sum 8 true
Path sum 9 true
If you store the parent of each node in MyNode, you can find the (reversed) path from the root to any node by getting the parent in a loop until it is null.
Also, your code for pathSum seems to be mixing booleans and ints, and you never check the value of sum.