I'm trying to create a Huffman Tree implementation, and included in that is a way to search for a character and return the Huffman code for it. I'm having a bit of trouble with it. This is my best attempt so far -
String lookupResult = "";
private void findPath(char ch, Node node, String path) {
if (node != null) {
if (node.left != null)
findPath(ch, node.left, path + '0');
if (node.right != null)
findPath(ch, node.right, path + '1');
if (node.left == null && node.right == null && node.key == ch) {
System.out.println(path);
lookupResult = path;
}
}
}
But instead of it returning the correct answer for a test ("01"), I get "101" and I'm not too sure how to fix it. Any help would be appreciated.
Related
I'm working on a program that accepts a string which represents a prefix format binary expression (such as (A(B(C)(D))(E(F)(G))) ). I've been stuck on a part of the algorithm to add the data to nodes based on the parenthesis from separate stacks (after A for root, '('indicates a left node while ')' followed by '(' indicates a right. My code seems to run well enough until I hit the following code:
if (focus != null && val == '(') {
char nodeVal = tree.pop();
Node node = new Node(nodeVal);
focus = root;
while(focus != null) {
focus = focus.leftNode;
}
focus = node;
It passes through the "if (focus != null)", but when it hits the while loop, it either returns an error, doesn't add the new node or creates an infinite loop (based on a few variations I've been trying. The full code for the method is as follows if it helps:
public void constructTree(String input) {
for(int i = input.length()-1; i>=0; i--) {
if(input.charAt(i) == '(' || input.charAt(i) == ')') {
paren.push(input.charAt(i));
}
else {
tree.push(input.charAt(i));
}
}
while(!paren.isEmpty()) {
char val = paren.pop();
Node focus = root;
Node parent;
if (val == ')' && root == null) {
throw new InvalidTreeSyntax("Your tree cannot be empty");
}
if (root == null) {
char nodeVal = tree.pop();
Node node = new Node(nodeVal);
root = node;
}
if (focus != null && val == '(') {
char nodeVal = tree.pop();
Node node = new Node(nodeVal);
focus = root;
while(focus != null) {
focus = focus.leftNode;
}
focus = node;
}
else if (focus != null && val == ')' && paren.peek()== '(' || paren.peek() == null) {
char nodeVal = tree.pop();
Node node = new Node(nodeVal);
paren.pop();
while(focus!= null) {
focus = focus.rightNode;
}
focus = node;
}
}
}
I'm sure it's a simple mistake, but after a belly full of turkey and not enough sleep, I'm brain dead and need some help!
This is a recursive solution.
record Node(char value, Node left, Node right) {}
static Node constructTree(Deque<Integer> que) {
if (que.peek() != '(')
return null;
que.pop();
if (que.peek() == '(' || que.peek() == ')')
throw new RuntimeException("node value expected");
char nodeValue = (char)(int)que.pop();
Node left = constructTree(que);
Node right = constructTree(que);
if (que.peek() != ')')
throw new RuntimeException("')' expected");
que.pop();
return new Node(nodeValue, left, right);
}
static Node consturctTree(String s) {
return constructTree(s.chars().boxed()
.collect(Collectors.toCollection(ArrayDeque::new)));
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
String source = "(A(B(C)(D))(E(F)(G)))";
Node root2 = consturctTree(source);
System.out.println(root2);
}
output: (edited)
Node[value=A,
left=Node[value=B,
left=Node[value=C, left=null, right=null],
right=Node[value=D, left=null, right=null]],
right=Node[value=E,
left=Node[value=F, left=null, right=null],
right=Node[value=G, left=null, right=null]]]
I want to delete a specific node using a key from a Ternary Search Tree. This works pretty well in most cases, but in some of my test sets, nodes that do not have a middle child also do not store values, which shouldn't happen.
I tried different methods I found online, but pretty much all of those few leave the tree in a dirty state, which makes searching a hassle, since you need to check if the leaf you found actually has a value, which shouldn't happen.
Here is my relevant code
private boolean hasChildren(Node x) {
return (x.left != null || x.mid != null || x.right != null);
}
private void reHang(Node x) {
if (hasChildren(x)) {
if (x.left != null) {
x.parent.mid = x.left;
x.left.right = x.right;
} else if (x.right != null) {
x.parent.mid = x.right;
}
}
}
private boolean remove(Node x, String key, int d) {
if (x == null) return false;
char c = key.charAt(d);
if (c < x.c) {
if (!remove(x.left, key, d)) {
x.left = null;
}
} else if (c > x.c) {
if (!remove(x.right, key, d)) {
x.right = null;
}
} else if (d < key.length() - 1) {
if (!remove(x.mid, key, d + 1)) {
x.mid = null;
if (x.val != null) return true;
}
} else {
x.val = null;
}
reHang(x);
return hasChildren(x);
}
private class Node
{
private Value val;
private char c;
private Node left, mid, right, parent;
}
Specifically, problems occur in this function I use for prefix lookups:
private Node getMidPath(Node x) {
if (x.left != null) return getMidPath(x.left);
if (x.mid == null) return x;
return getMidPath(x.mid);
}
Every Node that does not have a x.mid should have an x.val set, which is not always the case after remove, meaning I have dirty nodes.
Any help would be greatly appreciated.
You must see a ternary tree at was it is: Some nested Binary tree but witch each level have only on character as key instead of the whole string. Go down you binary trees until you string is exhausted. Here you will have two eventually references one to the actual data and and one two the actual subtree for longer string with same prefix. Now set the data to null. When the subtree reference is null remove the node. When now the entire subtree is empty continue with the subtree one character earlier. Here set subtree reference to null. Now is both references are null remove the node. When now the entire subtree is empty continue with the subtree one character earlier. And so on
I collapsed all of huffman nodes into one node and trying to build a tree by that node and make a code for each character(huffman leaf) but I can't manage it
I have already tried to write a method but it didn't work because it stops when the first code is created for the first character
this is my method:
public String createKey(Node node,String s){
if(node.right==null&&node.left==null) {
hashMap.put(node, s);
s="";
}
if (node.left!=null)
return createKey(node.left,s+"0");
if(node.right!=null)
return createKey(node.right,s+"1");
return s;
}
It's usually best to have a single return statement than to have multiple return statements. Your code doesn't visit right nodes because you are returning before that code is ever reached. Something like this will visit every node. You might have to play with the formatting of the results a bit.
public String createKey(Node node,String s){
if(node.right == null && node.left == null) {
hashMap.put(node, s);
s="";
}
if (node.left != null)
s += createKey(node.left, s + "0");
if(node.right != null)
s += createKey(node.right, s + "1");
return s;
}
Something like this would also work and maybe be easier to format results:
public String createKey(Node node,String s){
if(node.right == null && node.left == null) {
hashMap.put(node, s);
s="";
}
else if (node.left != null && node.right != null)
s = createKey(node.left, s + "0") + " " + createKey(node.right, s + "1");
else if (node.left != null)
s = createKey(node.left, s + "0");
else if(node.right != null)
s = createKey(node.right, s + "1");
return s;
}
To print a binary tree path with a leaf node value. When it backtracks, it should remove the '3' from the stack. How to modify the code to achieve? I can't find a place to pop the value from the stack.
// should print out "5 8 10", but it prints "5 3 8 10"
printPathWithStack(root, 5);
10
/ \
8 2
/ \ /
3 5 4
void printPathWithStack(Node root, int key)
{
Stack<Node> path = new Stack<Node>();
printPathWithStackHelper(root, key, path);
}
void printPathWithStackHelper(Node root, int key, Stack<Node> path)
{
if (root == null) {
return;
}
path.push(root);
if (root.data == key && root.left == null && root.right == null) {
while (!path.isEmpty()) {
System.out.print(path.pop().data + " ");
}
} else if (root.left == null && root.right == null){
path.pop();
}
printPathWithStackHelper(root.left, key, path);
printPathWithStackHelper(root.right, key, path);
}
Well, it's a bit strange to use the stack this way.
But for what it's worth, when backtracking you should simply discard all items where item.left or item.right is not equal the last retrieved item. This will give you the path to the root.
You can defer pushing into Stack until making recursive calls to left and right child.
if (root.data == key && root.left == null && root.right == null)
{
path.push(root);
while (!path.isEmpty())
{
System.out.print(path.pop().data + " ");
}
return;
}
else if (root.left == null && root.right == null)
{
return;
}
path.push(root);
printPathWithStackHelper(root.left, key, path);
printPathWithStackHelper(root.right, key, path);
Hope it addresses your problem!
P.S. Not tested the code fragment for general cases, hope you will do the required :)
I have a binary search tree. I know how to search using the search property. But my task is to search the tree without using search property.(Say, search in binary tree) This is how I have to search.
1. If you find the value in the current node return it.
2. else search in right. If not found in right, then search in left
3. If not found in the whole tree return null.
This is what i tried.
public Node search(int val)
{
Node target = this;
if(target.getVal() == val)
return this;
else if(target.getRight() == null && target.getLeft() == null)
return null;
if(target.getRight() != null)
{
return target.getRight().search(id);
}
if(target.getLeft() != null)
{
return target.getLeft().search(id);
}
return null;
}
Problem with my code is, if right child exists and val is not found in right I'm getting null value. (Not searching in left). How to resolve this?
public Node search(int val)
{
Node target = this;
if(target.getVal() == val)
return this;
else if(target.getRight() == null && target.getLeft() == null)
return null;
if(target.getRight() != null)
{
return target.getRight().search(id); //here lies the problem
}
if(target.getLeft() != null)
{
return target.getLeft().search(id);
}
return null;
}
The problem in your code is that you are returning the result of search in right subtree of the node being searched.
Here's the updated code
public Node search(int val)
{
Node target = null;
if(this.getVal() == val)
{
return this;
}
else if(this.getRight() == null && this.getLeft() == null)
return target;
if(this.getRight() != null)
{
target = this.getRight().search(id);
}
if(target==null && this.getLeft() != null)
{
target = this.getLeft().search(id);
}
return target;
}
This is untested code, but I'd change your logic a bit:
public Node search(int val)
{
if(this.getVal() == val)
return this;
if (this.getRight() != null) {
Node right = this.getRight().search(id);
if (right != null)
return right;
}
if (this.getLeft() != null) {
Node left = this.getLeft().search(id);
if (left != null)
return left;
}
return null;
}
In your version you are returning a solution with the sole requirement that the node on the right or left is not null. You have to return a solution only if a solution is found.