1257: 哈夫曼压缩

1257: 哈夫曼压缩

时间限制: 1 Sec  内存限制: 128 MB
提交: 1052  解决: 711
[提交] [状态] [讨论版] [命题人:外部导入]

题目描述

相信大家都对哈夫曼编码有所了解,通常利用哈夫曼编码来压缩数据。现在给你一个字符串,你需要统计其中字符出现的次数然后以出现次数为权值构建一棵哈夫曼树,例如字符串为ABBCCC,其中一种可能的编码是A = 00,B = 01,C = 1,那么这个字符串所对应的哈夫曼编码就是000101111,你的任务是求出字符串最终形成的哈夫曼编码的长度。

输入

一行由大写字母组成的字符串,且字符串长度不超过10000,该字符串最少包含一种字符。

输出

字符串的哈夫曼编码长度。

样例输入 Copy
ABBCCC
样例输出 Copy
9
来源/分类

贪心

import java.util.*;
//1257
// 定义哈夫曼树节点类
abstract class HuffmanTree implements Comparable<HuffmanTree> {
    public final int frequency; // 节点权值
 
    public HuffmanTree(int frequency) {
        this.frequency = frequency;
    }
 
    // 比较节点的权值
    public int compareTo(HuffmanTree tree) {
        return frequency - tree.frequency;
    }
}
 
// 内部节点类,表示非叶子节点
class InternalNode extends HuffmanTree {
    public final HuffmanTree left, right; // 左右子树
 
    public InternalNode(HuffmanTree left, HuffmanTree right) {
        super(left.frequency + right.frequency);
        this.left = left;
        this.right = right;
    }
}
 
// 叶子节点类,表示字符及其权值
class LeafNode extends HuffmanTree {
    public final char character; // 字符
 
    public LeafNode(char character, int frequency) {
        super(frequency);
        this.character = character;
    }
}
 
public class Main {
    // 构建哈夫曼树
    public static HuffmanTree buildHuffmanTree(String input) {
        // 统计字符出现的次数
        Map<Character, Integer> frequencyMap = new HashMap<>();
        for (char c : input.toCharArray()) {
            frequencyMap.put(c, frequencyMap.getOrDefault(c, 0) + 1);
        }
 
        // 使用优先队列构建哈夫曼树
        PriorityQueue<HuffmanTree> priorityQueue = new PriorityQueue<>();
        for (Map.Entry<Character, Integer> entry : frequencyMap.entrySet()) {
            priorityQueue.offer(new LeafNode(entry.getKey(), entry.getValue()));
        }
 
        // 合并节点直到只剩下一个根节点
        while (priorityQueue.size() > 1) {
            HuffmanTree left = priorityQueue.poll();
            HuffmanTree right = priorityQueue.poll();
            priorityQueue.offer(new InternalNode(left, right));
        }
 
        return priorityQueue.poll();
    }
 
    // 计算哈夫曼编码的长度
    public static int calculateHuffmanLength(HuffmanTree tree) {
        return calculateHuffmanLength(tree, 0);
    }
 
    private static int calculateHuffmanLength(HuffmanTree tree, int depth) {
        if (tree instanceof LeafNode) {
            return depth * ((LeafNode) tree).frequency;
        } else if (tree instanceof InternalNode) {
            InternalNode node = (InternalNode) tree;
            return calculateHuffmanLength(node.left, depth + 1) + calculateHuffmanLength(node.right, depth + 1);
        }
        return 0;
    }
 
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String input = scanner.nextLine().trim();
 
        HuffmanTree tree = buildHuffmanTree(input);
        int huffmanLength = calculateHuffmanLength(tree);
 
        System.out.println(huffmanLength);
    }
}

  • 11
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 哈夫曼压缩是一种基于编码的数据压缩算法。该算法通过建立字典树来对输入的数据进行编码,使得出现频率高的字符使用较短的编码,而出现频率低的字符使用较长的编码,以达到压缩数据的目的。 首先,对于要压缩的数据c,哈夫曼编码算法需要统计数据中各个字符的出现频率。然后,根据频率构建一颗哈夫曼树,这颗树的根节点对应的编码路径是最短的。接着,通过遍历哈夫曼树得到每个字符的编码,将编码与对应的字符一一对应保存在编码表中。 对于压缩c的过程,我们通过在编码表中查找c对应的编码,将其保存下来。最后,将所有的编码拼接起来,得到一个二进制的压缩结果。这个结果的长度可能比原数据c要短,实现了压缩效果。 相反地,哈夫曼解压是将二进制的压缩结果还原成原来的数据c。首先,我们将压缩结果按位解码成对应的编码,然后通过编码表查找得到原始的字符。最后,将所有的字符拼接起来,即可得到解压后的原始数据c。 哈夫曼压缩和解压c的核心思想就是使用变长编码来对输入数据进行表示,使得出现频率高的字符占用较少的位数,从而达到压缩的效果。通过构建哈夫曼树并生成编码表,可以实现高效的压缩和解压过程。哈夫曼压缩算法在无损数据压缩领域得到广泛应用,具有较好的压缩效果和运行效率。 ### 回答2: 哈夫曼压缩(Huffman compression)是一种无损压缩算法,常用于减小数据文件的存储空间。它基于哈夫曼编码,通过将出现频率高的字符用较短的位数表示,而将出现频率低的字符用较长的位数表示,从而减小整体文件的大小。 哈夫曼压缩的过程如下:首先,统计待压缩文件中每个字符出现的频率,并构建一个字符频率表。然后,根据字符频率表构建一个哈夫曼树,该树的每个叶节点对应一个字符,并使得字符频率越高的叶节点离根节点越近。接下来,根据哈夫曼树构建字符编码表,即不同字符对应的哈夫曼编码。最后,将原始文件中的每个字符用对应的哈夫曼编码替换,并将替换后的编码写入到压缩文件中。 解压哈夫曼压缩文件的过程与压缩相反:首先,读取压缩文件并解析每个哈夫曼编码,根据编码找到对应的字符。接着,根据哈夫曼编码表将压缩文件中的位串进行逐个解码,并还原成原始字符。最后,将解码后的字符连成一个字符串,并将该字符串写入到解压后的文件中。 总结来说,哈夫曼压缩利用字符的出现频率构建哈夫曼编码,将出现频率高的字符用较短的位数编码,从而减小文件的存储空间。解压则根据哈夫曼编码表对哈夫曼压缩文件进行解码,并恢复成原始文件。哈夫曼压缩和解压是一对互逆操作,通过该算法可以有效地减小文件的大小,并在解压时还原文件内容。 ### 回答3: 哈夫曼压缩和解压是一种常用的数据压缩算法。该算法通过统计数据中不同字符的出现频率,构建一个哈夫曼树来实现数据的无损压缩。 在压缩阶段,首先统计数据中各个字符的频率,然后根据频率构建一个哈夫曼树。哈夫曼树的构建过程如下:首先,将所有字符的频率与字符对应的叶结点放入一个优先队列中。然后,不断从队列中取出频率最小的两个结点,创建一个新结点作为它们的父节点,并将新结点的频率设置为这两个结点频率之和。接着,将新结点放回优先队列,重复此过程直到队列中只剩下一个结点,即为根节点。 在构建好哈夫曼树后,根据每个字符在树中的路径编码来生成对应的编码表。编码表中,每个字符对应一个二进制编码,通过根据字符在哈夫曼树上从根节点到叶节点的路径来生成。路径向左表示该位编码为0,向右表示该位编码为1。 然后,遍历原始数据中的每个字符,将其使用编码表中对应的二进制编码代替原来的字符。这样,数据就被压缩成了二进制数据。 在解压阶段,首先读取压缩后的二进制数据,并根据解压缩前的哈夫曼树,逐个比对读取到的二进制编码,还原出对应的字符。这样,压缩后的数据就被解压缩成了原始数据。 哈夫曼压缩和解压算法能够有效地减小数据的存储空间,但由于需要构建哈夫曼树和编码表,在解压阶段需要使用到这些信息,所以压缩和解压的过程是相互依赖的。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值