java实现赫夫曼编码封装

package com.coderman.datastruct.tree;

import org.junit.Test;

import java.util.*;

/**
 * 哈夫曼编码
 * @Author zhangyukang
 * @Date 2020/6/4 10:54
 * @Version 1.0
 **/
public class HuffmanCodingTest {

    //模拟要传输的数据
//    private static String data="i love you so so so much !";

    private static String data="i like like like java do you like a java";

    public static void main(String[] args) {
        // 统计各个字符对应的个数(次数作为权值)
        // i->1 ,v->1 ,e->1 ,y->1 ,u->1 , l->1 ,o->2 _->2
//        int[] array={1,1,1,1,1,1,2,2};
        HTree hTree = new HTree(data);
        System.out.println("要传输的字符串");
        System.out.println(data);
//        hTree.preOrder(hTree.getRoot());
        System.out.println("生成编码表");
        System.out.println(hTree.huffmanCodeTable);
        System.out.println("编码后的数据:【反码---> 每8位一个字节】");
        System.out.println(hTree.code());
        System.out.println("编码后的字节数组");
        System.out.println(Arrays.toString(hTree.zip()));
    }

    @Test
    public void test(){
        String name="zhangyukang is a cool boy~";
        HTree hTree = new HTree(name);
        byte[] data = hTree.getData();
        System.out.println(Arrays.toString(data));
    }
}

class HTree{

    private String value;

    private TNode root;

    private byte[] data;

    //对应的字符编码表
    public   Map<Character,String> huffmanCodeTable=new HashMap<>();

    private StringBuilder stringBuilder=new StringBuilder();

    public TNode getRoot() {
        return root;
    }

    public byte[] getData() {
        return data;
    }

    public void setRoot(TNode root) {
        this.root = root;
    }

    public HTree(String value){
        this.value=value;
        this.root=createTree(value);
        createHuffmanTable(this.root);
        this.data=zip();
    }

    public void createHuffmanTable(TNode root){
        createHuffmanTable(root,"",this.stringBuilder);
    }

    /**
     * 赫夫曼编码表
     * @return
     */
    public void createHuffmanTable(TNode current,String code,StringBuilder stringBuilder){
        StringBuilder stringBuilder1=new StringBuilder(stringBuilder);
        stringBuilder1.append(code);
        if(current!=null){
            if(current.getData()==null){
                //非叶子节点,递归
                //向左递归
                createHuffmanTable(current.getLeft(),"0",stringBuilder1);
                //向右递归
                createHuffmanTable(current.getRight(),"1",stringBuilder1);
            }else{
                huffmanCodeTable.put((char)current.getData().byteValue(),stringBuilder1.toString());
            }
        }
    }

    /**
     * 获取编码后要传输的数据
     * @return
     */
    public String code(){
        StringBuilder code= new StringBuilder();
        for (char c : this.value.toCharArray()) {
            String value = this.huffmanCodeTable.get(c);
            code.append(value);
        }
        return code.toString();
    }

    /**
     * 返回编码过后的字节数组
     * 8位一个字节
     * 1011000110011101011100111101111101100001001111101111101
     * 补码: 【0】= 10110001
     * 反码:【0】= 10110000
     * 原码:【0】= 11001111
     * 十进制:-
     * @return
     */
    public byte[] zip(){
        String code = code();
        //构造字节数组的长度
        int len=code.length()%8==0? (code.length()/8): ((code.length()/8)+1);

        byte[] bytes=new byte[len];
        int index=0;
        for(int i=0;i<code.length();i+=8){
            String substring;
            if(i+8>code.length()) {//不够8位
                substring = code.substring(i);
            }else {
                substring = code.substring(i, i + 8);
            }
            bytes[index]=(byte) Integer.parseInt(substring,2);
            index++;
        }
        return bytes;
    }

    /**
     * 创建赫夫曼树
     * @param value
     */
    private TNode createTree(String value) {
        //构建出节点集合
        List<TNode> tNodes=buildNodeList(value);
        //排序集合
        while (tNodes.size()>1){
            Collections.sort(tNodes);
            //取出最小的一个,和次小的一个节点重写构成一颗树
            TNode leftNode = tNodes.get(0);
            TNode rightNode= tNodes.get(1);
            TNode parent = new TNode(null,leftNode.getWeight()+rightNode.getWeight());
            parent.setLeft(leftNode);
            parent.setRight(rightNode);
            //移除
            tNodes.remove(leftNode);
            tNodes.remove(rightNode);
            //添加
            tNodes.add(parent);
        }
        return tNodes.get(0);
    }

    /**
     * 前序遍历
     * @param current
     */
    public void preOrder(TNode current){
        if(current!=null){
            System.out.println(current);
            preOrder(current.getLeft());
            preOrder(current.getRight());
        }
    }

    /**
     * build nodes
     * @param value
     * @return
     */
    private List<TNode> buildNodeList(String value) {
        byte[] bytes = value.getBytes();
        List<TNode> result=new ArrayList<>();
        Map<Byte,Integer> map=new HashMap<>();
        //统计每个字符出现的次数
        for (byte aByte : bytes) {
            map.merge(aByte, 1, Integer::sum);
        }
        //遍历Map,构建节点
        if(map.size()>0){
            for(Map.Entry<Byte,Integer> entry: map.entrySet()){
                TNode tNode = new TNode(entry.getKey(),entry.getValue());
                result.add(tNode);
            }
        }
        return result;
    }

}


class TNode implements Comparable<TNode>{
    private Byte data;//存放数据

    private int weight;//存放权重: 字符出现的次数

    private TNode left;

    private TNode right;

    public TNode(Byte data, int weight) {
        this.data = data;
        this.weight = weight;
    }

    public Byte getData() {
        return data;
    }

    public void setData(Byte data) {
        this.data = data;
    }

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }

    public TNode getLeft() {
        return left;
    }

    public void setLeft(TNode left) {
        this.left = left;
    }

    public TNode getRight() {
        return right;
    }

    public void setRight(TNode right) {
        this.right = right;
    }

    @Override
    public int compareTo(TNode o) {
        return this.weight-o.weight;
    }

    @Override
    public java.lang.String toString() {
        return "TNode{" +
                "data=" + (data==null? "null":(char)data.byteValue()) +
                ", weight=" + weight +
                '}';
    }
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是C++实现赫夫曼编码算法的代码,其中包括构造赫夫曼树和求解赫夫曼编码的函数: ```cpp #include <iostream> #include <queue> #include <vector> #include <string> #include <map> using namespace std; // 赫夫曼树结点 struct HuffmanNode { int weight; // 权值 char ch; // 字符 HuffmanNode *left, *right; // 左右子树 HuffmanNode(int w, char c = '\0') : weight(w), ch(c), left(nullptr), right(nullptr) {} }; // 比较器,用于优先队列 struct cmp { bool operator() (HuffmanNode* a, HuffmanNode* b) { return a->weight > b->weight; } }; // 构造赫夫曼树 HuffmanNode* buildHuffmanTree(int* weights, int n) { priority_queue<HuffmanNode*, vector<HuffmanNode*>, cmp> pq; for (int i = 0; i < n; i++) { pq.push(new HuffmanNode(weights[i], char('a' + i))); } while (pq.size() > 1) { HuffmanNode* left = pq.top(); pq.pop(); HuffmanNode* right = pq.top(); pq.pop(); HuffmanNode* parent = new HuffmanNode(left->weight + right->weight); parent->left = left; parent->right = right; pq.push(parent); } return pq.top(); } // 递归求解赫夫曼编码 void getHuffmanCode(HuffmanNode* root, string code, map<char, string>& res) { if (!root) return; if (!root->left && !root->right) { res[root->ch] = code; return; } getHuffmanCode(root->left, code + "0", res); getHuffmanCode(root->right, code + "1", res); } // 求解赫夫曼编码 map<char, string> HuffmanCoding(int* weights, int n) { HuffmanNode* root = buildHuffmanTree(weights, n); map<char, string> res; getHuffmanCode(root, "", res); return res; } int main() { int weights[] = {5, 2, 4, 7, 1, 3, 6}; int n = sizeof(weights) / sizeof(weights[0]); map<char, string> res = HuffmanCoding(weights, n); for (auto it = res.begin(); it != res.end(); it++) { cout << it->first << ": " << it->second << endl; } return 0; } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值