数据压缩算法之哈夫曼编码(HUFFMAN)的实现
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)的实现的更多相关文章
- 数据压缩之经典——哈夫曼编码(Huffman)
(笔记图片截图自课程Image and video processing: From Mars to Hollywood with a stop at the hospital的教学视频,使用时请注意 ...
- 赫夫曼\哈夫曼\霍夫曼编码 (Huffman Tree)
哈夫曼树 给定n个权值作为n的叶子结点,构造一棵二叉树,若带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree).哈夫曼树是带权路径长度最短的树,权值较大的结点离 ...
- 哈夫曼编码(Huffman coding)的那些事,(编码技术介绍和程序实现)
前言 哈夫曼编码(Huffman coding)是一种可变长的前缀码.哈夫曼编码使用的算法是David A. Huffman还是在MIT的学生时提出的,并且在1952年发表了名为<A Metho ...
- 采用霍夫曼编码(Huffman)画出字符串各字符编码的过程并求出各字符编码 --多媒体技术与应用
题目:有一个字符串:cabcedeacacdeddaaaba,问题: (1)采用霍夫曼编码画出编码的过程,并写出各字符的编码 (2)根据求得的编码,求得各编码需要的总位数 (3)求出整个字符串总编码长 ...
- 霍夫曼编码(Huffman)
题目:有一个字符串:cabcedeacacdeddaaaba,问题: (1)采用霍夫曼编码画出编码的过程,并写出各字符的编码 (2)根据求得的编码,求得各编码需要的总位数 (3)求出整个字符串总编码长 ...
- Python 算法(2) 哈夫曼编码 Huffman Encoding
这个问题原始是用来实现一个可变长度的编码问题,但可以总结成这样一个问题,假设我们有很多的叶子节点,每个节点都有一个权值w(可以是任何有意义的数值,比如它出现的概率),我们要用这些叶子节点构造一棵树,那 ...
- 霍夫曼编码(Huffman Coding)
霍夫曼编码(Huffman Coding)是一种编码方法,霍夫曼编码是可变字长编码(VLC)的一种. 霍夫曼编码使用变长编码表对源符号(如文件中的一个字母)进行编码,其中变长编码表是通过一种评估来源符 ...
- 哈夫曼编码的理解(Huffman Coding)
哈夫曼编码(Huffman Coding),又称霍夫曼编码,是一种编码方式,可变字长编码(VLC)的一种.Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长度最 ...
- HDU2527 哈夫曼编码
Safe Or Unsafe Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)To ...
随机推荐
- NO.1:自学python之路------Hello world、判断、循环
引言 人工智能如今越来越贴近生活,在这里将记录我自学python与tensorflow的过程.编程使用IDE:visual studio 2017,python版本3.6.4,tensorflow版本 ...
- 性能度量RMSE
回归问题的典型性能度量是均方根误差(RMSE:Root Mean Square Error).如下公式. m为是你计算RMSE的数据集中instance的数量. x(i)是第i个实例的特征值向量 ,y ...
- Centos7 Zabbix添加主机、图形、触发器
制作自定义key zabbix自带模板Template OS Linux (Template App Zabbix Agent)提供CPU.内存.磁盘.网卡等常规监控,只要新加主机关联此模板,就可自动 ...
- centos下安装升级python到python3.5
本文摘抄自:https://www.cnblogs.com/edward2013/p/5289056.html 请支持原版 CentOS7安装Python3.5 2. 安装Python的依赖包 ...
- 0329--Scrum团队准备工作
一.团队名称,团队目标.团队口号.团队照 1.团队名称:Blackhriar 2.团队目标:完成一个完善的,可以投入市场供用户使用,甚至具有一定商业价值的项目~come on! 3.团队口号:抱怨事件 ...
- winform default模式下和英文模式下 修改问题
1.修改控件大小.位置等属性在default模式下修改: 2.修改控件属性最好不要做鼠标拖动放大,拖动修改位置等,建议用属性栏中的数字来改变.
- 2018软工实践—Alpha冲刺(3)
队名 火箭少男100 组长博客 林燊大哥 作业博客 Alpha 冲鸭鸭鸭! 成员冲刺阶段情况 林燊(组长) 过去两天完成了哪些任务 协调各成员之间的工作 协助后端界面的开发 搭建项目运行的服务器环境 ...
- 团队Alpha冲刺(二)
目录 组员情况 组员1(组长):胡绪佩 组员2:胡青元 组员3:庄卉 组员4:家灿 组员5:凯琳 组员6:丹丹 组员7:家伟 组员8:政演 组员9:黄鸿杰 组员10:刘一好 组员11:何宇恒 展示组内 ...
- HDU 1257 最少拦截系统(最长递减子序列的条数)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1257 题解: #include<iostream> #include<cstdio ...
- MDL数据结构
微软的文档里对MDL的描述感觉语焉不详,这两天在找工作的间隙逆向+黑盒测试了一下MmBuildMdlForNonPagedPool,把得到的一些理解描述下来. 一.MDL数据结构 MDL是用来建立一块 ...