算法导论实验(六)哈夫曼编码源码:
public class Node {
public int key;
public char data;
public Node left;
public Node right;
}
public class Huffman {
public static void main(String[] args) {
List<Character> data=null;
Map<Character,Integer> map=new HashMap<>();
try {
data= getData(); //从data.txt文件中读取数据存放在data中
for(char c:data)
map.put(c,map.getOrDefault(c,0)+1); //统计各个字符的频率
} catch (FileNotFoundException e) {
e.printStackTrace();
}
Node root=HuffmanBuild(map);
Map<Character,String> encodeData=new HashMap<>();
encode(root,encodeData,new StringBuilder());
List<String> writeData=new ArrayList<>();
int encodeLen=0;
for(char c:data){
writeData.add(encodeData.get(c));
encodeLen+=encodeData.get(c).length();
}
write(writeData);
int oldLen=0;
if(map.size()==1)
oldLen=1*data.size();
else
oldLen= (int) ((Math.ceil(Math.log(map.size())/Math.log(2)))*data.size());
DecimalFormat df = new DecimalFormat( "0.00");
System.out.println("压缩率:"+df.format(100*(double)encodeLen/ oldLen)+"%");
}
static public void encode(Node root,Map<Character,String> map,StringBuilder sb){
if(root.left==null&&root.right==null){
map.put(root.data,sb.toString());
return;
}
sb.append("0");
encode(root.left,map,sb);
sb.deleteCharAt(sb.length()-1);
sb.append("1");
encode(root.right,map,sb);
sb.deleteCharAt(sb.length()-1);
}
static public Node HuffmanBuild(Map<Character,Integer> map){
PriorityQueue<Node> pq=new PriorityQueue<>((o1,o2)->o1.key-o2.key);
Set<Map.Entry<Character, Integer>> entries = map.entrySet();
for(Map.Entry<Character,Integer> entry:entries){
Node node=new Node();
node.data=entry.getKey();
node.key=entry.getValue();
pq.offer(node);
}
int n=pq.size();
for(int i=0;i<n-1;i++){
Node z=new Node();
z.left=pq.poll();
z.right=pq.poll();
z.key=z.left.key+z.right.key;
pq.offer(z);
}
return pq.poll();
}
public static List getData() throws FileNotFoundException {
List<Character> list=new ArrayList<>();
try(InputStream in=new FileInputStream("src/algorithm/project5/data.txt")){
int n;
while((n=in.read())!=-1){
char c=(char)n;
list.add(c);
}
} catch (IOException e) {
e.printStackTrace();
}
return list;
}
public static void write(List<String> data){
File file = new File("src/algorithm/project5/encode.txt");
if(!file.exists()){
file.mkdir();
}
try(Writer out =new FileWriter(file)) {
for(int i=0;i<data.size();i++){
out.write(data.get(i));
out.flush();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}