HUFFMAN编码可以很有效的压缩数据,通常可以压缩20%到90%的空间(算法导论)。具体的压缩率取决于数据的特性(词频)。如果采取标准的语料库进行编码,一般可以得到比较满意的编码结果(对不同文件产生不同压缩率的折中方法)。

本文采取对单独一个文件进行编码的方式来演示此压缩算法的使用。

分为下面几个步骤:

1.统计词频数据

2.词频数据转换成HUFFMAN算法能够处理的类型(本文为HuffmanNode,内部有存储词频和树节点的结构)

  (1)由输入的HuffmanNode[]数组创建最小优先级队列

  (2)依次取出队列中的每两个节点,然后由此两个节点构造一个新的节点,然后在重新插入回队列。直到队列中只剩唯一一个节点。

    此节点为编码树的根节点。

  (3)依次遍历原来输入的每个HUFFMAN节点,得到每个字符的对应编码(压缩使用)。

  (4)解码方式,依次输入0/1字符码到算法,算法遍历产生的编码树,如果有返回字符,则得到解码字符。

词频统计的实现:

 public class FrequencyCounter
{
public IEnumerable<KeyValuePair<char, int>> MapReduce(string str)
{
//the GroupBy method is acting as the map,
//while the Select method does the job of reducing the intermediate results into the final list of results.
var wordOccurrences = str
.GroupBy(w => w)
.Select(intermediate => new
{
Key = intermediate.Key,
Value = intermediate.Sum(w => )
})
.OrderBy(kvp => kvp.Value);
IEnumerable<KeyValuePair<char, int>> kvps = from wo in wordOccurrences select new KeyValuePair<char, int>(wo.Key, wo.Value);
return kvps;
}
}

MapReduce

HUFFMAN编码类的实现:

 public class Huffman
{
private List<HuffmanNode> originalNodes;
private HuffmanNode rootNode;
public Huffman(IEnumerable<KeyValuePair<char, int>> kvps)
{
//保存原始数据
var tmpOriginalNodes = from kvp in kvps select new HuffmanNode(kvp.Key, kvp.Value);
//创建最小优先队列,并输入数据
MinPriorityQueue<HuffmanNode> minQueue = new MinPriorityQueue<HuffmanNode>();
originalNodes = new List<HuffmanNode>();
foreach (var node in tmpOriginalNodes)
{
originalNodes.Add(node);
minQueue.Insert(node);
}
//建造编码树,并取得编码树的根节点
while (!minQueue.IsEmpty)
{
HuffmanNode left = minQueue.ExtractMin();
if (minQueue.IsEmpty)
{
rootNode = left;
break;
}
HuffmanNode right = minQueue.ExtractMin();
HuffmanNode newNode = new HuffmanNode(null, left.Value + right.Value, left, right);
left.Parent = newNode;
right.Parent = newNode;
minQueue.Insert(newNode);
}
}
//只接受单个char的加密
public string Encode(char sourceChar)
{
HuffmanNode hn = originalNodes.FirstOrDefault(n => n.Key == sourceChar);
if (hn == null) return null;
HuffmanNode parent = hn.Parent;
StringBuilder rtn = new StringBuilder();
while (parent != null)
{
if (Object.ReferenceEquals(parent.Left, hn))//左孩子,编码为0
{
rtn.Insert(, "", );
}
else//右孩子,编码为1
{
rtn.Insert(, "", );
}
hn = parent;
parent = parent.Parent;
}
return rtn.ToString();
}
//只接受一个字符的解码输出
public bool Decode(string string01, out char? output)
{
HuffmanNode tmpNode = rootNode;
char[] chars = string01.Trim().ToCharArray();
for (int i = ; i < chars.Count(); i++)
{
if (chars[i] == '') tmpNode = tmpNode.Left;
if (chars[i] == '') tmpNode = tmpNode.Right;
}
if (tmpNode != null && tmpNode.Left == null && tmpNode.Right==null)
{
output = tmpNode.Key;
return true;
}
else
{
output = null;
return false;
}
} class HuffmanNode : IHeapValue
{
public HuffmanNode(char? key, int value, HuffmanNode left = null, HuffmanNode right = null)
{
this.Left = left;
this.Right = right;
this.Key = key;
this.Value = value;
}
public HuffmanNode Left { get; private set; }
public HuffmanNode Right { get; private set; }
public HuffmanNode Parent { get; set; }
public char? Key { get; private set; }
public int Value { get; set; }
}
}

对文本进行编码的用法:

 FrequencyCounter fc = new FrequencyCounter();
var kvps = fc.MapReduce(这里是你的文本);
hm = new Huffman(kvps);
StringBuilder sb = new StringBuilder();
string ori =这里是你的文本;
char[] chararray = ori.ToCharArray();
for (int i = ; i < chararray.Length; i++)
{
sb.Append(hm.Encode(chararray[i]));
}

对编码进行解码:

            string bstr =你的编码后的文本;
StringBuilder sb = new StringBuilder();
char? outchar = null;
string tmpStr = null;
for (int i = ; i < bstr.Length; i++)
{
tmpStr = tmpStr + bstr[i];
if (hm.Decode(tmpStr, out outchar))
{
tmpStr = null;
sb.Append(outchar);
}
}

测试效果,可以看到压缩效果还是很明显的:

完毕。

作者:Andy Zeng

欢迎任何形式的转载,但请务必注明出处。

http://www.cnblogs.com/andyzeng/p/3703321.html

数据压缩算法之哈夫曼编码(HUFFMAN)的实现的更多相关文章

  1. 数据压缩之经典——哈夫曼编码(Huffman)

    (笔记图片截图自课程Image and video processing: From Mars to Hollywood with a stop at the hospital的教学视频,使用时请注意 ...

  2. 赫夫曼\哈夫曼\霍夫曼编码 (Huffman Tree)

    哈夫曼树 给定n个权值作为n的叶子结点,构造一棵二叉树,若带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree).哈夫曼树是带权路径长度最短的树,权值较大的结点离 ...

  3. 哈夫曼编码(Huffman coding)的那些事,(编码技术介绍和程序实现)

    前言 哈夫曼编码(Huffman coding)是一种可变长的前缀码.哈夫曼编码使用的算法是David A. Huffman还是在MIT的学生时提出的,并且在1952年发表了名为<A Metho ...

  4. 采用霍夫曼编码(Huffman)画出字符串各字符编码的过程并求出各字符编码 --多媒体技术与应用

    题目:有一个字符串:cabcedeacacdeddaaaba,问题: (1)采用霍夫曼编码画出编码的过程,并写出各字符的编码 (2)根据求得的编码,求得各编码需要的总位数 (3)求出整个字符串总编码长 ...

  5. 霍夫曼编码(Huffman)

    题目:有一个字符串:cabcedeacacdeddaaaba,问题: (1)采用霍夫曼编码画出编码的过程,并写出各字符的编码 (2)根据求得的编码,求得各编码需要的总位数 (3)求出整个字符串总编码长 ...

  6. Python 算法(2) 哈夫曼编码 Huffman Encoding

    这个问题原始是用来实现一个可变长度的编码问题,但可以总结成这样一个问题,假设我们有很多的叶子节点,每个节点都有一个权值w(可以是任何有意义的数值,比如它出现的概率),我们要用这些叶子节点构造一棵树,那 ...

  7. 霍夫曼编码(Huffman Coding)

    霍夫曼编码(Huffman Coding)是一种编码方法,霍夫曼编码是可变字长编码(VLC)的一种. 霍夫曼编码使用变长编码表对源符号(如文件中的一个字母)进行编码,其中变长编码表是通过一种评估来源符 ...

  8. 哈夫曼编码的理解(Huffman Coding)

    哈夫曼编码(Huffman Coding),又称霍夫曼编码,是一种编码方式,可变字长编码(VLC)的一种.Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长度最 ...

  9. HDU2527 哈夫曼编码

    Safe Or Unsafe Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

随机推荐

  1. mysql优化建议21条

    转自: http://blog.csdn.net/waferleo/article/details/7179009 今 天,数据库的操作越来越成为整个应用的性能瓶颈了,这点对于Web应用尤其明显.关于 ...

  2. Python 并行分布式框架:Celery 超详细介绍

    本博客摘自:http://blog.csdn.net/liuxiaochen123/article/details/47981111 先来一张图,这是在网上最多的一张Celery的图了,确实描述的非常 ...

  3. scrum立会报告+燃尽图(第三周第七次)

    此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2286 项目地址:https://coding.net/u/wuyy694 ...

  4. c语言的知识与能力自评

    知识与能力 C语言最早是由美国Bell实验室设计的,主要用作UNIX系统的工作语言,后来发展成为一种通用语言.C与UNIX有密切的关系,C最早是在PDP机器上用UNIX操作系统上开发的,后来又用C语言 ...

  5. XML XPath语法总结

    刚刚遇到一个多重查询xmlDoc.SelectSingleNode("Root/Element[@Name='大气象'][@Age='30']")根据innerText查询xmlD ...

  6. 七周七语言之使用prolog解决爱因斯坦斑马难题

    如果你想获得更好的阅读体验,可以前往我在 github 上的博客进行阅读,http://lcomplete.github.io/blog/2013/06/28/sevenlang-prolog/. 目 ...

  7. Java的一些细节问题

    一.Java求余%的结果符号取决于除数的符号位:小数也可以求余,余数仍为小数. package com.test; public class Test { /** * @author 容杰龙 */ p ...

  8. 软工alpha阶段个人总结

    一.个人总结 类别 具体技能和面试问题 现在的回答(大三下) 语言 最拿手的语言之一,代码量是多少? java,代码量在一万行左右 语言 最拿手的语言之二,代码量是多少? C语言,代码量在五千行左右 ...

  9. 4th 课堂SCRM会议旁观记录

    项目名称:基于C#的连连看设计 小组名称:待定 小组成员:张政.张金生.武志远.李权 Master:张政 项目已完成部分: 现阶段已经实现了一定的功能,可以运行使用,进行第一关的游戏. 今天计划要完成 ...

  10. python OCR 图形识别

    1.pip install pyocr 2.pip install PIL 3.安装tesseract-ocr http://jaist.dl.sourceforge.net/project/tess ...