Java哈夫曼编码与解码

代码过程:先用map计数文件字符频率,然后将字符与其频率存入一个节点,再将节点按频率顺序放入优先级队列,然后每次从队列取出2个构建一个树,再插入队列,反复进行直到队列中只有一个树为止,哈夫曼树就创建好了。

然后用一个递归的方法将每个字符与其对应二进制码存入map集合中,反向对应关系也存一个map方便解码,之后就比较简单了。

package TwoChildTree;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.HashMap;
import java.util.Map;

class Node1 {
    Node1 left;
    Node1 right;
    int data;
    char c;

    public Node1(char c, int data) {//字符及对应频率
        this.c = c;
        this.data = data;
    }
}

class Link {
    Link next;
    Node1 node;

    public Link(Node1 node) {//存入节点
        this.node = node;
    }
}

public class HafumanTree {
    static Link front;
    static String s;
    static HashMap<Character, Integer> map = new HashMap<>();

    static void mapPut() {//统计各字符出现频率
        for (char ch : s.toCharArray()) {
            if (map.containsKey(ch))
                map.put(ch, map.get(ch) + 1);
            else {
                map.put(ch, 1);
            }
        }
    }

    static void insert(Node1 node) {//链表的插入方法
        Link link = new Link(node);
        if (!isEmpty()) {
            Link previous = front;
            Link current = front;
            while (node.data > current.node.data) {
                previous = current;
                current = current.next;
                if (current == null) {
                    previous.next = link;
                    return;
                }
            }
            if (current == front) {
                link.next = front;
                front = link;
                return;
            }
            previous.next = link;
            link.next = current;
        } else
            front = link;
    }

    static Node1 delete() {//链表删除方法
        Node1 temp = front.node;
        front = front.next;
        return temp;
    }

    static boolean isEmpty() {
        return (front == null);
    }

    static Node1 joinToTree() {//创建哈夫曼树
        Node1 root = null;
        while (!isEmpty()) {
            Node1 n1 = delete();
            Node1 n2 = delete();
            root = new Node1('\0', n1.data + n2.data);
            root.left = n1;
            root.right = n2;
            if (isEmpty())
                break;
            insert(root);
        }
        return root;
    }

    //取出字符与其对应二进制码
    static void display(Node1 node, String str, Map<Character, String> m) {

        if (node != null) {// 不能用while
            if (node.left == null && node.right == null) {
                char c = node.c;
                m.put(c, str);
            }

            display(node.left, str + 0, m);
            display(node.right, str + 1, m);

        }

    }
//解码
    static void decode(Map<String, Character> m) {
        try {
            FileReader fr = new FileReader("D:\\2.txt");
            FileWriter fw = new FileWriter("D:\\3.txt");
            int i;
            StringBuilder sb=new StringBuilder();
            while ((i = fr.read()) != -1) {
                sb.append((char)i);//问题在这里,要转为char
                if(m.containsKey(sb.toString())){
                    fw.write(m.get(sb.toString()));
                    sb.delete(0, sb.capacity());
                }
                }
            
            fw.close();
            fr.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
//编码
    static void encode(String str, Map<Character, String> m) {
        StringBuilder sb = new StringBuilder();
        for (char c : str.toCharArray())
            sb.append(m.get(c));
        try {
            File file = new File("D:\\2.txt");
            FileWriter fw = new FileWriter(file);
            BufferedWriter br = new BufferedWriter(fw);
            br.write(sb.toString());
            br.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder();
        File file = new File("D:\\1.txt");
        try {
            FileReader fr = new FileReader(file);
            int i;
            while ((i = fr.read()) != -1)
                sb.append((char) i);
            s = sb.toString();
            fr.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        mapPut();
        for (char c : map.keySet()) {
            insert(new Node1(c, map.get(c)));
        }
        Node1 node = joinToTree();
        String str = "";
        HashMap<Character, String> m = new HashMap<>();
        display(node, str, m);
        HashMap<String, Character> m2 = new HashMap<>();
        for (char c : m.keySet())
            m2.put(m.get(c), c);
        for (String ss : m2.keySet())
            System.out.println(ss + " " + m2.get(ss));
        encode(s, m);
        decode(m2);

    }
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值