哈夫曼编码huffmanCoding

 自用保存

import java.util.*;

class Huffman {
    public static void main(String[] args) {
        HuffmanTree huffmanTree = new HuffmanTree("bibbity_bobbity");
        huffmanTree.createTree();
        String encoded = huffmanTree.encode();
        System.out.println("Encoded String: " + encoded);
        System.out.println("Decoded String: " + huffmanTree.decode(encoded));
    }
}

class TreeNode {
    String letter = "";
    int frequency = 0;
    TreeNode left = null, right = null;

    public TreeNode(String letter, int frequency) {
        this.letter = letter;
        this.frequency = frequency;
    }

    public TreeNode(int frequency, TreeNode left, TreeNode right) {
        this.frequency = frequency;
        this.left = left;
        this.right = right;
    }
}

class HuffmanTree {
    private Map<String, Integer> frequencyMap = new HashMap<>();
    private Map<String, String> codeBook = new HashMap<>()  ,   reverseCodeBook = new HashMap<>();
    private TreeNode root;
    private String stringToEncode;

    public HuffmanTree(String stringToEncode) {
        this.stringToEncode = stringToEncode;
    }

    public void createTree() {
        // 记录频次
        for (int i = 0; i < stringToEncode.length(); i++) {
            String key = Character.toString(stringToEncode.charAt(i));
            if (!frequencyMap.containsKey(key)) {
                frequencyMap.put(key, 1);
            } else {
                int frequency = frequencyMap.get(key) + 1;
                frequencyMap.replace(key, frequency);
            }
        }
        // ComparingInt(o -> o.frequency) 默认升序
        // 如Queue<int[]> minHeap = new PiorityQueue<>(Comparator.comparingInt(a -> a[1]));
        Queue<TreeNode> pq = new PriorityQueue<>(Comparator.comparingInt(o -> o.frequency));
        for (Map.Entry<String, Integer> m : frequencyMap.entrySet()) {
            pq.add(new TreeNode(m.getKey(), m.getValue()));
        }
        while (pq.size() > 1) {
            TreeNode left = pq.remove();
            TreeNode right = pq.remove();
            pq.add(new TreeNode(left.frequency + right.frequency, left, right));
        }
        root = pq.remove();
    }

    /***
     *
     * @param node 节点
     * @param code 每个叶子节点的编码
     */
    private void traverse(TreeNode node, StringBuilder code) {
        if (node.left == null && node.right == null) { // 到达叶子节点 放入codeBook(它是个map)
            codeBook.put(node.letter, code.toString());
        }
        if (node.left != null) {
            traverse(node.left, code.append(0));
            code.deleteCharAt(code.length() - 1);
        }
        if (node.right != null) {
            traverse(node.right, code.append(1));
            code.deleteCharAt(code.length() - 1);
        }
    }

    public void printCodeBook() {
        System.out.println("Code Book");
        for (Map.Entry<String, String> m : codeBook.entrySet()) {
            System.out.println(m.getKey() + "\t" + m.getValue());
        }
        System.out.println();
    }

    private void CodeBookReverse() {
        for (Map.Entry<String, String> m : codeBook.entrySet()) {
            reverseCodeBook.put(m.getValue(), m.getKey());
        }
    }

    /***
     * 编码
     * @return 返回编码串
     */
    public String encode() {
        traverse(root, new StringBuilder());
        StringBuilder encode = new StringBuilder();
        // 遍历句子中的每个字母 对照codeBook翻译为bit码
        for (int i = 0; i < stringToEncode.length(); i++) {
            String k = Character.toString(stringToEncode.charAt(i));
            encode.append(codeBook.get(k));
        }
        printCodeBook();
        return encode.toString();
    }

    /***
     * 当key = "0"时 检测到字典中有相对的字母 直接编码  (此时encoded串循环到"0")
     * 然后key清空 直到下一轮读入"111"  (此时encoded串循环到"0111")
     * key清空 直到下一轮读到"0" (此时encoded串循环到"01110")
     * @param encoded 已经编码的串
     * @return 返回解码串
     */
    public String decode(String encoded) {
        StringBuilder decoded = new StringBuilder()  ,   key = new StringBuilder();
        CodeBookReverse(); // 填写reverseCodeBook 相当于把codeBook里面的键和值对调
        for (int i = 0; i < encoded.length(); i++) {
            key = key.append(encoded.charAt(i));
            if (reverseCodeBook.containsKey(key.toString())) {
                decoded.append(reverseCodeBook.get(key.toString()));
                key = new StringBuilder(); // 这一步相当于某个bit编码被采用后直接丢弃
            }
        }
        return decoded.toString();
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是C语言实现哈夫曼编码的代码,其中包含注释: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX 1000 // 定义最大编码长度 typedef struct { int weight; // 权值 int parent, lchild, rchild; // 双亲和左右孩子结点 } HTNode, *HuffmanTree; typedef char **HuffmanCode; void Select(HuffmanTree HT, int n, int *s1, int *s2) { // 在前n个结点中选择权值最小的两个结点s1和s2 int i, min; for (i = 1; i <= n; i++) { if (HT[i].parent == 0) { min = i; break; } } for (i = 1; i <= n; i++) { if (HT[i].parent == 0 && HT[i].weight < HT[min].weight) { min = i; } } *s1 = min; for (i = 1; i <= n; i++) { if (HT[i].parent == 0 && i != *s1) { min = i; break; } } for (i = 1; i <= n; i++) { if (HT[i].parent == 0 && HT[i].weight < HT[min].weight && i != *s1) { min = i; } } *s2 = min; } void CreateHuffmanTree(HuffmanTree *HT, int n) { // 由n个权值为w的结点构建哈夫曼树HT if (n <= 1) { return; } int m = 2 * n - 1; *HT = (HuffmanTree) malloc((m + 1) * sizeof(HTNode)); int i; for (i = 1; i <= m; i++) { (*HT)[i].parent = 0; (*HT)[i].lchild = 0; (*HT)[i].rchild = 0; } for (i = 1; i <= n; i++) { scanf("%d", &((*HT)[i].weight)); } int s1, s2; for (i = n + 1; i <= m; i++) { Select(*HT, i - 1, &s1, &s2); (*HT)[s1].parent = i; (*HT)[s2].parent = i; (*HT)[i].lchild = s1; (*HT)[i].rchild = s2; (*HT)[i].weight = (*HT)[s1].weight + (*HT)[s2].weight; } } void CreateHuffmanCode(HuffmanTree HT, HuffmanCode *HC, int n) { // 根据哈夫曼树HT求出n个字符的哈夫曼编码HC *HC = (HuffmanCode) malloc((n + 1) * sizeof(char *)); char *cd = (char *) malloc(n * sizeof(char)); cd[n - 1] = '\0'; int i, c, f; for (i = 1; i <= n; i++) { int start = n - 1; for (c = i, f = HT[i].parent; f != 0; c = f, f = HT[f].parent) { if (HT[f].lchild == c) { cd[--start] = '0'; } else { cd[--start] = '1'; } } (*HC)[i] = (char *) malloc((n - start) * sizeof(char)); strcpy((*HC)[i], &cd[start]); } free(cd); } void HuffmanCoding(HuffmanTree HT, HuffmanCode HC, int n) { // 输入n个字符的权值,建立哈夫曼树HT,并求出n个字符的哈夫曼编码HC CreateHuffmanTree(&HT, n); CreateHuffmanCode(HT, &HC, n); } void HuffmanDecoding(HuffmanTree HT, int n) { // 将01序列翻译成原来的文本字符 printf("请输入01序列:\n"); char str[MAX]; scanf("%s", str); int i, c = 2 * n - 1; for (i = 0; str[i] != '\0'; i++) { if (str[i] == '0') { c = HT[c].lchild; } else { c = HT[c].rchild; } if (HT[c].lchild == 0 && HT[c].rchild == 0) { printf("%d", c); c = 2 * n - 1; } } } int main() { int n; printf("请输入字符的个数n:\n"); scanf("%d", &n); HuffmanTree HT; HuffmanCode HC; HuffmanCoding(HT, HC, n); int i; printf("各字符的哈夫曼编码如下:\n"); for (i = 1; i <= n; i++) { printf("%d %s\n", i, HC[i]); } HuffmanDecoding(HT, n); return 0; } ``` 以上是C语言实现哈夫曼编码的代码,可以根据输入的字符权值构建哈夫曼树,并输出各字符对应的哈夫曼编码。同时,可以将传输的文本转换成对应的哈夫曼编码01序列,并将哈夫曼编码01序列翻译成原来的文本字符。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值