哈夫曼编码-Java实现

哈夫曼编码主要用于数据压缩,用更少的位表示更多的数据。

首先对原始数据进行统计,计算每个字符出现的次数,然后建立哈夫曼树。
哈夫曼树也叫最优二叉树(哈夫曼树)。

解码时,对编码后的数据,从哈夫曼树的根出发,遇到一个叶子节点,则译出一个字符,重复此步骤,直到译出所有字符。

建立哈夫曼树的标准是,总长最短,译码时,结果唯一。每个字符的编码不能是其它字符的前置。

public class Node<T> {
    int key;
    T charData;

    Node leftChild;
    Node rightChild;

    public void displayNode(){

    }

}
public class Tree implements Comparable<Tree>{
    private Node root;

    public Node getRoot() {
        return root;
    }

    public void setRoot(Node root) {
        this.root = root;
    }
    /**
     *中序遍历法
     */
    public void inDisplay(Node node){
        if (node!=null){
            inDisplay(node.leftChild);
            System.out.println(node.key+":"+node.charData);
            inDisplay(node.rightChild);
        }
    }
    public void postDisplay(Node node){
        if (node!=null){
            postDisplay(node.leftChild);
            postDisplay(node.rightChild);
            System.out.print(node.key+":"+node.charData);

        }
    }
    @Override
    public int compareTo(Tree o) {
        if (this.root.key>o.root.key){
            return 1;
        }else if (this.root.key==o.root.key){
            return 0;
        }else {
            return -1;
        }
    }
}
public class Huffman {
    private Map<Character,Integer> map=new HashMap<>();
    private Map<Character,String> ce=new HashMap<>();
    private PriorityQueue<Tree> trees=new PriorityQueue<>();
    private String source;
    private String result;
    public void init(String source){
        this.source=source;
        char[] chars= source.toCharArray();
        for (char c :chars){
            if (!map.containsKey(c)){
                map.put(c,1);
            }else {
                map.put(c,map.get(c)+1);
            }
        }
        afterInit();
    }

    private void afterInit() {
        map.forEach((c,count)->{
            Node<Character> node=new Node<>();
            node.key=count;
            node.charData=c;

            Tree tree=new Tree();
            tree.setRoot(node);

            trees.add(tree);
        });
    }

    public void build(){
        while (this.trees.size()>1){
            Tree left=this.trees.poll();
            Tree right=this.trees.poll();

            Node node=new Node();
            node.key=left.getRoot().key+right.getRoot().key;
            node.leftChild=left.getRoot();
            node.rightChild=right.getRoot();

            left.setRoot(node);
            this.trees.add(left);
        }
    }
    public void encoding(){
        Tree tree=this.trees.peek();
        this.encoding(tree.getRoot(),"");
    }
    public String encodingResult(){
        StringBuilder sb=new StringBuilder();
        char[] chars= source.toCharArray();
        for (char c :chars){
            sb.append(ce.get(c)+' ');
        }
        return sb.toString();
    }
    private void encoding(Node<Character> node,String encoding){
        if (node!=null){
            if (node.leftChild==null && node.rightChild==null){
                ce.put(node.charData,encoding);
            }
            encoding(node.leftChild,encoding+"0");
            encoding(node.rightChild,encoding+"1");
        }
    }
    public void displayTree(){
        Tree tree=this.trees.peek();
        tree.inDisplay(tree.getRoot());
    }
    public void displayEncodeing(){
        ce.forEach((k,v)->{
            System.out.println(k+":"+v);
        });
    }
    public static void main(String[] args) {
        String source="ABAACDC";
        Huffman huffman=new Huffman();
        huffman.init(source);
        huffman.build();
        huffman.displayTree();
        System.out.println("-------");
        huffman.encoding();
        huffman.displayEncodeing();
        System.out.println(source+":"+huffman.encodingResult());
    }
}

运行结果:

3:A
7:null
2:C
4:null
1:B
2:null
1:D
-------
A:0
B:110
C:10
D:111
ABAACDC:0 110 0 0 10 111 10  //加空格是为了方便看

原始数据ABAACDC的编码结果是0110001011110

解码时,每取一位,则遍历一次树,发现节点是叶子节点时,则译出一个字符。不是叶子节点,则记住该节点,取下一位后,从上次记录的节点接着遍历。

  • 3
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
哈夫曼编码是一种数据压缩算法,用于将数据压缩为更小的数据集。在哈夫曼编码中,频率越高的字符被编码为较短的编码,频率较低的字符被编码为较长的编码。以下是一个基本的Java实现: 1. 定义一个节点类,表示哈夫曼树上的节点。 ```java class Node { char data; // 字符 int freq; // 频率 Node left, right; // 左子树和右子树 // 构造函数 public Node(char data, int freq) { this.data = data; this.freq = freq; left = null; right = null; } } ``` 2. 定义一个比较器类,用于按照频率比较节点。 ```java class NodeComparator implements Comparator<Node> { public int compare(Node node1, Node node2) { return node1.freq - node2.freq; } } ``` 3. 定义一个构建哈夫曼树的方法。 ```java public static Node buildHuffmanTree(char[] chars, int[] freqs) { PriorityQueue<Node> pq = new PriorityQueue<Node>(new NodeComparator()); // 将所有字符和频率的节点加入优先队列 for (int i = 0; i < chars.length; i++) { pq.offer(new Node(chars[i], freqs[i])); } // 构建哈夫曼树 while (pq.size() > 1) { Node left = pq.poll(); Node right = pq.poll(); Node parent = new Node('$', left.freq + right.freq); parent.left = left; parent.right = right; pq.offer(parent); } // 返回根节点 return pq.poll(); } ``` 4. 定义一个打印哈夫曼编码的方法。 ```java public static void printHuffmanCodes(Node root, String code) { if (root == null) { return; } if (root.data != '$') { System.out.println(root.data + ": " + code); } printHuffmanCodes(root.left, code + "0"); printHuffmanCodes(root.right, code + "1"); } ``` 5. 调用以上方法,实现哈夫曼编码。 ```java public static void main(String[] args) { char[] chars = { 'a', 'b', 'c', 'd', 'e', 'f' }; int[] freqs = { 5, 9, 12, 13, 16, 45 }; Node root = buildHuffmanTree(chars, freqs); printHuffmanCodes(root, ""); } ``` 以上代码将输出以下内容: ``` a: 1100 c: 100 b: 1110 e: 01 d: 101 f: 00 ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值