码迷,mamicode.com
首页 > 编程语言 > 详细

Huffman编码——Java实现

时间:2014-08-21 20:51:24      阅读:209      评论:0      收藏:0      [点我收藏+]

标签:des   http   java   io   strong   for   数据   ar   

Huffman编码 是一种编码方式,常用于无损压缩。本文只介绍用Java语言来实现该编码方式的算法和数据结构。
 
Huffman编码的核心在于构建一颗最优化的二叉树,首先要得到一个原数据编码中的【编码:频率】的列表,然后根据列表构建二叉树,最后对二叉树编码。

 

第一步: 计算出每个词(编码)出现的频次,并输出到一个列表

例如字符串:"this is an example of a huffman tree", 它的二进制编码是11101001101000110100111100111000001101001111001110000011000011101110100000110010111110001100001110110111100001101100110010110000011011111100110100000110000110000011010001110101110011011001101101101110000111011101000001110100111001011001011100101

英文字母的表示只需要一个byte, 所以我们每次取二进制中的一个byte,放入HashMap<Byte,Node<Byte,Integer>>, 其中Byte作为HashMap的key,它的Value是一个Node<Byte, Integer> 。Node保存了byte值和出现的频次,将来用于构建Huffman树。遍历二进制编码,最后输出List<Node<Byte,Integer>> 。

代码如下:

  1. String source = "this is an example of a huffman tree";
  2. byte[] sourceBytes = source.getBytes();
  3. HashMap<Byte, Node<Byte, Integer>> frequency = new HashMap<>();
  4. for (byte key : sourceBytes) {
  5. if (frequency.containsKey(key)) {
  6. frequency.put(key, new Node<>(key, frequency.get(key).weight + 1));
  7. else {
  8. frequency.put(key, new Node<>(key, 1));
  9. }
  10. }
  11. List<Node<Byte, Integer>> nodes = new ArrayList<>(frequency.values());

nodes包含每个字母出现的频次:[o:1, l:1, u:1, r:1, p:1, x:1, n:2, m:2, h:2, i:2, t:2, s:2, f:3, e:4, a:4, :7]

第二步:构建最优二叉树

  1. while (nodes.size() > 1) {
  2. Node<Byte, Integer> first = nodes.get(0);
  3. Node<Byte, Integer> second = nodes.get(1);
  4. nodes.add(new Node<>(null, first.weight + second.weight, first, second));
  5. nodes.remove(0);
  6. nodes.remove(0);
  7. Collections.sort(nodes, (left, right) -> left.weight - right.weight);
  8. }

根据优先队列算法我们总是取队列中weight(频次)最小的两个节点,把它们的weight相加得到一个新的节点放入队列中,它们本身则作为新节点的左右子节点,构建结束时列表中剩余的唯一节点就是Huffman树的root。

        HuffmanTree<Byte, Integer> huffmanTree = new HuffmanTree<>(nodes.get(0));

第三步:给Huffman树编码

在第二步中构造完成了一颗尚未编码的树,编码其实就是给每一个节点一个唯一的编码,而且这个编码不可能是其他节点编码的前缀,根据Huffman编码的算法要做到这样很简单: 初始root的编码为空(长度为0),从root开始遍历,左子节点编码=父节点编码+0,右子节点编码=父节点编码+1 。

  1. setCode(this.root, new BitArray(0));
  2. privatevoid setCode(Node<K, V> node, BitArray code) {
  3. node.code = code;
  4. if (node.left != null) {
  5. BitArray leftCode = newBitArray(node.code, false);
  6. setCode(node.left, leftCode);
  7. }
  8. if (node.right != null) {
  9. BitArray rightCode = newBitArray(node.code, true);
  10. setCode(node.right, rightCode);
  11. }
  12. }

遍历输出结果:[e:4:000,a:4:001,n:2:0100,m:2:0101,h:2:0110,i:2:0111,t:2:1000,s:2:1001,o:1:10100,l:1:10101,u:1:10110,r:1:10111,p:1:11000,x:1:11001,f:3:1101, :7:111] 

完毕, 全部代码下载:

------------------------------------------分割线------------------------------------------

更多精彩linux视频教程,尽在51CTO学院:
bubuko.com,布布扣
 

------------------------------------------分割线------------------------------------------

 

Huffman编码——Java实现,布布扣,bubuko.com

Huffman编码——Java实现

标签:des   http   java   io   strong   for   数据   ar   

原文地址:http://www.cnblogs.com/virgo121/p/3927866.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!