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;
}
Related
There's a practice problem that I've been working on that's been confusing me.
Define a function treeLevelOrder which satisfies the following claim:
If Q is a binary search tree of integers, then treeLevelOrder(Q) is the String representation of the contents of Q according to their level in the tree.
We get this tree as an example
9
/ \
5 16
/ \ / \
1 7 12 19
The value of the expression treeLevelOrder(Q) in this case would be
"[9,5,16,1,7,12,19]".
I've seen similar problems, but they don't follow the same format that I'm looking for, wanting to print by level order or as ordered tuples. Here's some sample code I've been working on:
private String treeLevelOrder(Node Q)
{
if (Q.left == null && Q.right == null)
return "[" + Q.datum + "]";
else if (Q.left == null && Q.right != null)
return "[" + Q.datum + ", "+Q.right.datum+"]" + treeLevelOrder(Q.right);
else if (Q.left !=null && Q.right == null)
return"[" + Q.datum + ", "+Q.left.datum+", *]"+ treeLevelOrder(T.left);
else
return "[" + Q.datum + ", "+Q.left.datum+", "+Q.right.datum+"]" +
treeLevelOrder(Q.left) + treeLevelOrder(Q.right);
}
Any assistance would be helpful.
EDIT: Okay, so I've been experimenting with the level order example at Geeks for Geeks, thank you curlyBraces, that would be closer to what I'm looking for, though I can't figure out to make it return a string. Here's the code they use:
/* function to print level order traversal of tree*/
void printLevelOrder()
{
int h = height(root);
int i;
for (i=1; i<=h; i++)
printGivenLevel(root, i);
}
/* Compute the "height" of a tree -- the number of
nodes along the longest path from the root node
down to the farthest leaf node.*/
int height(Node root)
{
if (root == null)
return 0;
else
{
/* compute height of each subtree */
int lheight = height(root.left);
int rheight = height(root.right);
/* use the larger one */
if (lheight > rheight)
return(lheight+1);
else return(rheight+1);
}
}
/* Print nodes at the given level */
void printGivenLevel (Node root ,int level)
{
if (root == null)
return;
if (level == 1)
System.out.print(root.data + ", ");
else if (level > 1)
{
printGivenLevel(root.left, level-1);
printGivenLevel(root.right, level-1);
}
}
Any ideas?
Here's an implementation using while loop and two queues to keep track of all the nodes:
public String treeLevelOrder(Node root) {
StringBuilder result = new StringBuilder("");
Queue<Node> current = new LinkedList<>();
Queue<Node> other = new LinkedList<>();
if(root != null)
current.add(root);
while(!current.isEmpty()) {
while(!current.isEmpty()) {
Node node = current.remove();
result.append(",");
result.append(node.datum);
// adding children to the other queue
if(node.left != null)
other.add(node.left);
if(node.right != null)
other.add(node.right);
}
// swapping the queues
Queue<Node> temp = current;
current = other;
other = temp;
}
// building final string
if(result.length() == 0)
result.append("[");
else
result.setCharAt(0,'[');
result.append("]");
return result.toString();
}
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 5 years ago.
Ok, so I wanted to write a delete method that works for any "delete-case" for Binary Search Trees and this is my attempt:
public void delete(int key) {
if (root.value == key) {
root = root.right;
root.left = root.right.left;
return;
}
else {
deleteRecursive(key, root); ***LINE 58***
}
}
public void deleteRecursive(int key, BinaryNode node) {
if (node == null) {
System.out.println("ERROR");
return;
}
else {
if (key < node.value) {
// continue search on left
if (node.left.value == key) {
if (node.left.left == null && node.left.right == null) {
node.left = null;
}
else if (node.left.left == null){
node.left = node.left.right;
}
else if (node.left.right == null){
node.left = node.left.left;
}
else{
node.left = node.left.right;
node.left.left = node.left.right.left; ***LINE 83***
}
}
else {
deleteRecursive (key, node.left);
}
}
else if (key > node.value){
// continue search on right
if (node.right.value == key) {
if (node.right.left == null && node.right.right == null) {
node.right = null;
}
else if (node.right.left == null){
node.right = node.right.right;
}
else if (node.right.right == null){
}
else if (node.left.left != null && node.left.right != null){
node.right = node.right.right;
node.right.left = node.right.right.left;
}
}
else {
deleteRecursive (key, node.right);
}
}
}
}
But when I actually use the delete method in Main its gives out a NullPointerException.
The error-message reads :
Exception in thread "main" java.lang.NullPointerException
at BinaryTree.deleteRecursive(BinaryTree.java:83)
at BinaryTree.delete(BinaryTree.java:58)
at Main.main(Main.java:14)
So I assume that it is in line 83 and 58 (marked in code).
I've been sitting here for the last hour trying to figure it out and can't seem to get it.
I'm not the best in Java so I thought i could look for some help here! :)
Here are all the files to run the program (everything except for the delete method was already given) : https://www.dropbox.com/sh/r1bt2880hnn6tjm/AADsRsOOzuiNKHp-ZC-IrvVta?dl=0
Since you are trying to remove from Binary Search Tree, better make it totally recursive rather than partially.
private BinaryNode deleteRecursive( int data,BinaryNode node) {
if(node==null){
return null;
}
if(data==node.value)
{
if(node.left!=null && node.right!=null){
BinaryNode minNode = getHighestNodeFromRight(node.right);
node.value = minNode.value;
node.right = deleteRecursive(minNode.value, node.right);
//System.out.println(minNode);
}
else if(node.left==null){
return node.right;
}
else{
return node.left;
}
}
else if(data>node.value){
node.right = deleteRecursive( data,node.right);
}
else{
node.left = deleteRecursive(data, node.left);
}
return node;
}
public BinaryNode getHighestNodeFromRight(BinaryNode node){
if(node.left==null){
return node;
}
else{
BinaryNode n = getHighestNodeFromRight(node.left);
return n;
}
}
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.
I am currently trying to implement a dictionary using a search tree. (The exercise tells me to use such a structure). My tree is made out of nodes that save 2 strings: abreviere(the abreviation of a phrase) and acronim(the phrase). Here is my implementation so far:
Node Class:
public class Nod {
String acronim;
String abreviere;
Nod st,dr;
Nod(String acronim,String abreviere){
this.acronim = acronim;
this.abreviere = abreviere;
st = null;
dr = null;
}
}
Tree Class:
Constructor and insert:
public class Arbore {
Nod root;
Arbore(Nod x){
root = x;
}
public void insert(Nod x,Nod curr){
if(curr.acronim.compareTo(x.acronim) < 0){
if(curr.st == null){
curr.st = new Nod(x.acronim,x.abreviere);
}
else insert(x,curr.st);
}
else if(curr.dr == null){
curr.dr = new Nod(x.acronim, x.abreviere);
}
else insert(x,curr.dr);
}
}
I made them to work. I don't understand why I can't have this code instead:
public class Arbore {
Nod root;
Arbore(){
}
public void insert(Nod x,Nod curr){
if(curr == null) {curr = x; return;}
if(curr.acronim.compareTo(x.acronim) < 0){
if(curr.st == null){
curr.st = new Nod(x.acronim,x.abreviere);
}
else insert(x,curr.st);
}
else if(curr.dr == null){
curr.dr = new Nod(x.acronim, x.abreviere);
}
else insert(x,curr.dr);
}
This wouldn't save my structure either (I am clearly missing something and seems to be related). The problem I am facing now is deleting a node. I have to search for an abreviation(abreviere) and if I find it I must print the phrase and delete the node. These are the methods that I use to do this:
public void search(String acronim){
if(root.acronim.compareTo(acronim) == 0) delete(root);
if(root.acronim.compareTo(acronim) < 0) search(acronim,root.st);
if(root.acronim.compareTo(acronim) > 0) search(acronim,root.dr);
}
private void search(String acronim,Nod curr){
if(curr == null){System.out.println("Nu exista"); return;}
if(curr.acronim.compareTo(acronim) == 0) this.delete(curr);
if(curr.acronim.compareTo(acronim) < 0) this.search(acronim,curr.st);
if(curr.acronim.compareTo(acronim) > 0) this.search(acronim,curr.dr);
}
private void delete(Nod x){
if(x.st == null && x.dr == null){ x = null; System.out.println("deleting");}
else if(x.st == null && x.dr != null) {x = x.dr;System.out.println("deleting right");}
else if(x.st != null && x.dr == null) {x = x.st;System.out.println("deleting left");}
else{
System.out.println("Il deletez");
Nod aux = new Nod(x.acronim,x.abreviere);
x.abreviere = x.st.abreviere;
x.acronim = x.st.acronim;
x.st.abreviere = aux.abreviere;
x.st.acronim = aux.acronim;
delete(x.st);
}
}
They seem to do the job(from the printed messages) . However the changes don't save, after I apply the method I am left with the same tree. Here is the printing method that shows me the current tree:
public String inordine(Nod root){
if(root == null) return "";
return inordine(root.st) + afis(root) + inordine(root.dr);
}
private String afis(Nod n){
if(n == null) return "E nula?!";
return n.abreviere + "->" + n.acronim + "\n";
}
public void afisare(){
System.out.println(inordine(this.root));
}
What am I doing wrong? Is it the garbage collector or something? I use my class like this:
public static void main(String[] args) throws FileNotFoundException, IOException {
FileReader fr = new FileReader("Acronime.txt");
BufferedReader bf = new BufferedReader(fr);
String line = bf.readLine();
String[] array = line.split("=>");
Nod x = new Nod(array[0],array[1]);
Arbore a = new Arbore(x);
while((line = bf.readLine()) != null){
String[] array2 = line.split("=>");
Nod y = new Nod(array2[0],array2[1]);
a.insert(y,a.root);
}
a.afisare();
a.search("JSE");
a.afisare();
}
The words come like this but this part works .
JSE=>JavaScript Encoding
ESP=>Enhanced Serial Port
MSB=>Most Significant Byte
CDRAM=>Cached Dynamic RAM
EMI=>Electro-Magnetic Interference
CDRAM=>Cached Dynamic RAM
AIFF=>Audio Interface File
BASM=>Built in AsseMbler
After looking at the suggested post I changed 2 rows in the delete method and added 1 more method:
Changed Rows:
else if(x.st == null && x.dr != null) {copy(x,x.dr); x.dr = null; System.out.println("deleting right");}
else if(x.st != null && x.dr == null) {copy(x,x.st); x.st = null; System.out.println("deleting left");}
This way the changes stick(if you want to know why read the question from the suggested post below).
In the end the question is : "How to delete an instance of a class because you can't do it with x = null;? "
About the constructor:
In the method you would like to use (with the empty constructor) you need to set the class member root at some point. Something like this should do it:
public void insert(Nod x,Nod curr){
if(curr == null) {
this.root = x;
return;
}
...
About deletion
I don't understand the case when st and dr is not null. You seem to keep the tree structure intact but switch the payload data (abreviere, acronim) of the st side and then delte the st node. I don't get it yet. I will update my answer when I understand better.
You can't destroy an instance of a class in java like I was trying to do in the delete method if(x.st == null && x.dr == null){ x = null;} . To delete the node from the tree you have to find the parent of x and then parent.x = null. This way the reference to x is lost and the garbage collector does his job.
This is because , like #Seelenvirtuose said, java uses pass-by-value which you can read more about in the link that he provided: click!
I can't seem to think of a way to solve this. At least not an elegant way. The function should determine if a given tree is a binary search tree. It seems to work (no duplicates are allowed now though).
This is where the function starts:
isBinarySearchTree(root)
Function:
public static boolean isBinarySearchTree(Node node) {
if (node.leftchild != null) {
if (node.leftchild.key < node.key)
isBinarySearchTree(node.leftchild);
else {
System.out.println("false: " + node + " -> " + node.leftchild);
return false;
}
}
if (node.rightchild != null) {
if (node.rightchild.key > node.key)
isBinarySearchTree(node.rightchild);
else {
System.out.println("false: " + node + " -> " + node.rightchild);
return false;
}
}
return true;
}
Obviously there is something wrong with the way I want to return. This would work if all the boolean return values would be in a logical && chain. The return value should only be true if all return values are true.
How would I have to rewrite the function to work like that? Or is it even possible?
This should work, I guess :
public static boolean isBinarySearchTree(Node node, int key) {
if (node.leftchild != null && node.leftchild.key < key || node.rightchild != null && node.rightchild.key > key) {
return false;
} else {
return (node.leftchild != null ? isBinarySearchTree(node.leftchild, node.leftchild.key) : true) && (node.rightchild != null ? isBinarySearchTree(node.rightchild, node.rightchild.key) : true);
}
}
You need to logically AND the results of your test on the left and test on the right, and return the result, something like return (leftnode == null || (leftnode.key < key && isBinarySearchTree(leftnode))) && (rightnode == null || (key < rightnode.key && isBinarySearchTree(rightnode)));. It might be clearer to break that into several lines, though.
public static boolean isBinarySearchTree(Node node) {
if(node==null)
return false;
if(node.left!=null &&node.key <node.left||node.right!=null &&node.key >node.right)
return false;
if((getMax(node.left)>getMin(node.right)) //Left subtree should not have a value which larger than min in right subtree
return false;
//check recurisvely left and right subtrees
if(!(isBinarySearchTree(node.left)&&isBinarySearchTree(node.right)))
return false;
return true;