|
| 1 | + |
| 2 | +import java.util.Comparator; |
| 3 | +import java.util.Iterator; |
| 4 | +import java.util.LinkedList; |
| 5 | +import java.util.List; |
| 6 | +import java.util.Scanner; |
| 7 | +import java.util.Stack; |
| 8 | +/** |
| 9 | + * |
| 10 | + * @author Mayank Kumar (mk9440) |
| 11 | + */ |
| 12 | +/* |
| 13 | +Output : |
| 14 | +
|
| 15 | +Enter number of distinct letters |
| 16 | +6 |
| 17 | +Enter letters with its frequncy to encode |
| 18 | +Enter letter : a |
| 19 | +Enter frequncy : 45 |
| 20 | +
|
| 21 | +Enter letter : b |
| 22 | +Enter frequncy : 13 |
| 23 | +
|
| 24 | +Enter letter : c |
| 25 | +Enter frequncy : 12 |
| 26 | +
|
| 27 | +Enter letter : d |
| 28 | +Enter frequncy : 16 |
| 29 | +
|
| 30 | +Enter letter : e |
| 31 | +Enter frequncy : 9 |
| 32 | +
|
| 33 | +Enter letter : f |
| 34 | +Enter frequncy : 5 |
| 35 | +
|
| 36 | +Letter Encoded Form |
| 37 | +a 0 |
| 38 | +b 1 0 1 |
| 39 | +c 1 0 0 |
| 40 | +d 1 1 1 |
| 41 | +e 1 1 0 1 |
| 42 | +f 1 1 0 0 |
| 43 | +
|
| 44 | +*/ |
| 45 | + |
| 46 | +class Node{ |
| 47 | +String letr=""; |
| 48 | +int freq=0,data=0; |
| 49 | +Node left=null,right=null; |
| 50 | +} |
| 51 | + |
| 52 | +//A comparator class to sort list on the basis of their frequency |
| 53 | +class comp implements Comparator<Node>{ |
| 54 | + @Override |
| 55 | + public int compare(Node o1, Node o2) { |
| 56 | + if(o1.freq>o2.freq){return 1;} |
| 57 | + else if(o1.freq<o2.freq){return -1;} |
| 58 | + else{return 0;} |
| 59 | + } |
| 60 | +} |
| 61 | + |
| 62 | + |
| 63 | +public class Huffman { |
| 64 | + |
| 65 | + // A simple function to print a given list |
| 66 | + //I just made it for debugging |
| 67 | + public static void print_list(List li){ |
| 68 | + Iterator<Node> it=li.iterator(); |
| 69 | + while(it.hasNext()){Node n=it.next();System.out.print(n.freq+" ");}System.out.println(); |
| 70 | + } |
| 71 | + |
| 72 | + //Function for making tree (Huffman Tree) |
| 73 | + public static Node make_huffmann_tree(List li){ |
| 74 | + //Sorting list in increasing order of its letter frequency |
| 75 | + li.sort(new comp()); |
| 76 | + Node temp=null; |
| 77 | + Iterator it=li.iterator(); |
| 78 | + //System.out.println(li.size()); |
| 79 | + //Loop for making huffman tree till only single node remains in list |
| 80 | + while(true){ |
| 81 | + temp=new Node(); |
| 82 | + //a and b are Node which are to be combine to make its parent |
| 83 | + Node a=new Node(),b=new Node(); |
| 84 | + a=null;b=null; |
| 85 | + //checking if list is eligible for combining or not |
| 86 | + //here first assignment of it.next in a will always be true as list till end will |
| 87 | + //must have atleast one node |
| 88 | + a=(Node)it.next(); |
| 89 | + //Below condition is to check either list has 2nd node or not to combine |
| 90 | + //If this condition will be false, then it means construction of huffman tree is completed |
| 91 | + if(it.hasNext()){b=(Node)it.next();} |
| 92 | + //Combining first two smallest nodes in list to make its parent whose frequncy |
| 93 | + //will be equals to sum of frequency of these two nodes |
| 94 | + if(b!=null){ |
| 95 | + temp.freq=a.freq+b.freq;a.data=0;b.data=1;//assigining 0 and 1 to left and right nodes |
| 96 | + temp.left=a;temp.right=b; |
| 97 | + //after combing, removing first two nodes in list which are already combined |
| 98 | + li.remove(0);//removes first element which is now combined -step1 |
| 99 | + li.remove(0);//removes 2nd element which comes on 1st position after deleting first in step1 |
| 100 | + li.add(temp);//adding new combined node to list |
| 101 | + //print_list(li); //For visualizing each combination step |
| 102 | + } |
| 103 | + //Sorting after combining to again repeat above on sorted frequency list |
| 104 | + li.sort(new comp()); |
| 105 | + it=li.iterator();//resetting list pointer to first node (head/root of tree) |
| 106 | + if(li.size()==1){return (Node)it.next();} //base condition ,returning root of huffman tree |
| 107 | + } |
| 108 | +} |
| 109 | + |
| 110 | + //Function for finding path between root and given letter ch |
| 111 | + public static void dfs(Node n,String ch){ |
| 112 | + Stack<Node> st=new Stack(); // stack for storing path |
| 113 | + int freq=n.freq; // recording root freq to avoid it adding in path encoding |
| 114 | + find_path_and_encode(st,n,ch,freq); |
| 115 | + } |
| 116 | + |
| 117 | + //A simple utility function to print stack (Used for printing path) |
| 118 | + public static void print_path(Stack<Node> st){ |
| 119 | + for(int i=0;i<st.size();i++){ |
| 120 | + System.out.print(st.elementAt(i).data+" "); |
| 121 | + } |
| 122 | + } |
| 123 | + |
| 124 | + public static void find_path_and_encode(Stack<Node> st,Node root,String s,int f){ |
| 125 | + //Base condition |
| 126 | + if(root!= null){ |
| 127 | + if(root.freq!=f){st.push(root);} // avoiding root to add in path/encoding bits |
| 128 | + if(root.letr.equals(s)){print_path(st);return;} // Recursion stopping condition when path gets founded |
| 129 | + find_path_and_encode(st,root.left,s,f); |
| 130 | + find_path_and_encode(st,root.right,s,f); |
| 131 | + //Popping if path not found in right or left of this node,because we previously |
| 132 | + //pushed this node in taking a mindset that it might be in path |
| 133 | + st.pop(); |
| 134 | + } |
| 135 | + } |
| 136 | + |
| 137 | + public static void main(String args[]){ |
| 138 | + List <Node> li=new LinkedList<>(); |
| 139 | + Scanner in=new Scanner(System.in); |
| 140 | + System.out.println("Enter number of distinct letters "); |
| 141 | + int n=in.nextInt(); |
| 142 | + String s[]=new String[n]; |
| 143 | + System.out.print("Enter letters with its frequncy to encode\n"); |
| 144 | + for(int i=0;i<n;i++){ |
| 145 | + Node a=new Node(); |
| 146 | + System.out.print("Enter letter : "); |
| 147 | + a.letr=in.next();s[i]=a.letr; |
| 148 | + System.out.print("Enter frequncy : "); |
| 149 | + a.freq=in.nextInt();System.out.println(); |
| 150 | + li.add(a); |
| 151 | + } |
| 152 | + Node root=new Node(); |
| 153 | + root=make_huffmann_tree(li); |
| 154 | + System.out.println("Letter\t\tEncoded Form"); |
| 155 | + for(int i=0;i<n;i++){ |
| 156 | + System.out.print(s[i]+"\t\t");dfs(root,s[i]);System.out.println();} |
| 157 | + } |
| 158 | +} |
0 commit comments