views:

153

answers:

2

So i must say that i love this site because its sooooo helpful and now i have another question! my Huffman tree which i had asked about earlier has another problem! here is the code:

package huffman;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.PriorityQueue;
import java.util.Scanner;

public class Huffman {

    public ArrayList<Frequency> fileReader(String file)
    {
        ArrayList<Frequency> al = new ArrayList<Frequency>();
        Scanner s;
        try {

            s = new Scanner(new FileReader(file)).useDelimiter("");
            while (s.hasNext())
            {
                boolean found = false;
                int i = 0;
                String temp = s.next();
                while(!found)
                {


                    if(al.size() == i && !found)
                    {
                        found = true;
                        al.add(new Frequency(temp, 1));
                    }
                    else if(temp.equals(al.get(i).getString()))
                    {
                        int tempNum = al.get(i).getFreq() + 1;
                        al.get(i).setFreq(tempNum);
                        found = true;
                    }
                    i++;

                }



            }
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return al;
    }
    public Frequency buildTree(ArrayList<Frequency> al)
    {
        Frequency r = al.get(1);
        PriorityQueue<Frequency> pq = new PriorityQueue<Frequency>();
        for(int i = 0; i < al.size(); i++)
        {
            pq.add(al.get(i));          
        }
        /*while(pq.size() > 0)
        {
            System.out.println(pq.remove().getString());
        }*/

        for(int i = 0; i < al.size() - 1; i++)
        {   
           Frequency p = pq.remove(); 
           Frequency q = pq.remove();
           int temp = p.getFreq() + q.getFreq();
           r = new Frequency(null, temp);
           r.left = p; 
           r.right = q;
           pq.add(r);  // put in the correct place in the priority queue
        }
        pq.remove(); // leave the priority queue empty
        return(r); // this is the root of the tree built

    }

    public void inOrder(Frequency top)
    {
        if(top == null)
        {
            return;
        }
        else
        {
            inOrder(top.left);
            System.out.print(top.getString() +", ");
            inOrder(top.right);
            return;
        }
    }
    public void printFreq(ArrayList<Frequency> al)
    {
        for(int i = 0; i < al.size(); i++)
        {
            System.out.println(al.get(i).getString() + "; " + al.get(i).getFreq());
        }
    }

}

What needs to be done now is i need to create a method that will search through the tree to find the binary code (011001 etc) to the specific character. what is the best way to do this? i thought maybe i would do a normal search through the tree as if it were an avl tree going to the right if its bigger or left if its smaller. but because the nodes dont use ints doubles etc. but only using objects that contain characters as strings or null to signify its not a leaf but only a root. the other option would be to do an inorder run through to find the leaf that im looking for but at the same time how would i determine if i went right so many times or left so many times to get the character. Any suggestions or ideas would be much appreciated!

package huffman;

public class Frequency implements Comparable  {
    private String s;
    private int n;
    public Frequency left;
    public Frequency right;

    Frequency(String s, int n)
    {
        this.s = s;
        this.n = n;
    }
    public String getString()
    {
        return s;
    }
    public int getFreq()
    {
        return n;
    }
    public void setFreq(int n)
    {
        this.n = n;
    }
    @Override
    public int compareTo(Object arg0) {
        Frequency other = (Frequency)arg0;

        return n < other.n ? -1 : (n == other.n ? 0 : 1);
    }
}

Ok So what im trying to do is find the binary code to actually get to each character so if i were trying to encode aabbbcccc how would i create a string holding the binary code for a going left is 0 and going right is 1. what has me confused is because u cant determine where anything is because the tree is obviously unbalanced and there is no determining if a character is right or left of where u are. so you have to search through the whole tree but if you get to a node that isnt what you are looking for you have back track to another root to get to the other leaves.

+1  A: 

Remember, if you have 1001, you will never have a 10010 or 10011. So your basic method looks like this (in pseudocode):

if(input == thisNode.key) return thisNode.value
if(input.endsWith(1)) return search(thisNode.left)
else return search(thisNode.right)

I didn't read your program to figure out how to integrate it, but that's a key element of huffman encoding in a nutshell

Try something like this - you're trying to find token. So if you wanted to find the String for "10010", you'd do search(root,"10010")

String search(Frequency top, String token) {
    return search(top,token,0);
}

// depending on your tree, you may have to switch top.left and top.right
String search(Frequency top, String token, int depth) {
    if(token.length() == depth) return "NOT FOUND";
    if(token.length() == depth - 1) return top.getString();
    if(token.charAt(depth) == '0') return search(top.left,token,depth+1);
    else return search(top.right,token,depth+1);

}
glowcoder
so the object im using should have a key holding the binary code for it? so i can just access that directly from the object that im looking for?
Zieklecknerizer
Hold on a sec I'll take a look at your program and see if I can offer any insight. This sounds suspiciously like homework - if it is you should add the homework tag. :)
glowcoder
yeah it is HW guess i should then haha
Zieklecknerizer
Post the frequency class.
glowcoder
yeah that would work to decode a file that was created but if i wanted to find out the token for each character what would i do?
Zieklecknerizer
+1  A: 

Traverse through the huffman tree nodes to get a map like {'a': "1001", 'b': "10001"} etc. You can use this map to get the binary code to a specific character.

If you need to do in reverse, just handle it as a state machine:

state = huffman_root
for each bit
    if (state.type == 'leaf')
        output(state.data);
        state = huffman_root
    state = state.leaves[bit]

Honestly said, I didn't look into your code. It ought be pretty obvious what to do with the fancy tree.

Cheery
In a huffman tree, non-leaf nodes can have data.
glowcoder
That sounds like fun. But what's the point of having data in non-leaf nodes?
Cheery