数据压缩算法之哈夫曼编码(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 ...
随机推荐
- MobSF 框架安装使用部署
1.MobSF 简介 MobSF是Mobile Security Framework的缩写,这是一款智能化的开源移动应用(Android.IOS.Windows)测试框架,可以对应用进行动态.静态分析 ...
- loadrunner socket协议问题归纳(3)
摘要:通过实例讲解loadrunner中的socket协议性能测试的一种测试方法,如何不依赖loadrunner既定规则,自行控制收发数据包 关键词:Loadrunner,socket,自行控制,收发 ...
- Split the Number(思维)
You are given an integer x. Your task is to split the number x into exactly n strictly positive inte ...
- 冲刺ing-4
第四次Scrum冲刺 队员完成的任务 队员 完成任务 吴伟华 Leangoo的看板截图,燃尽图 蔺皓雯 编写博客,学习后端设计 蔡晨旸 学习后端设计 曾茜 后端设计 鲁婧楠 服务器建构 杨池宇 学习后 ...
- 软工1816 · Alpha冲刺(9/10)
团队信息 队名:爸爸饿了 组长博客:here 作业博客:here 组员情况 组员1(组长):王彬 过去两天完成了哪些任务 学习jQuery的AJAX部分的基础知识,对web端如何异步获取服务器信息有了 ...
- asp.net登录状态验证
文章:ASP.NET 登录验证 文章:ASP.NET MVC下判断用户登录和授权状态方法 文章:.net学习笔记---HttpHandle与HttpModule 第一篇文章,介绍了 1)早期的Base ...
- 团队作业4——第一次项目冲刺(Alpha版本)第一次
一.会议内容 制定任务内容 制作leangoo表格 初步工作 二.各人工作 成员 计划任务 遇见难题 贡献比 塗家瑜(组长) 后端与数据库通讯 无 1 张新磊 表设计 无 1 姚燕彬 测试计划编写 无 ...
- WCF RestFull提交数据超出限额解决方法
最近在使用wcf restfull时出现了超大数据提交出错的问题. 服务端会返回错误:服务器处理请求时遇到错误.有关构造有效服务请求的内容,请参阅服务帮助页.异常消息为“反序列化对象 属于类型 Yes ...
- 淘宝免费ip地址查询导致服务堵死的坑
1.业务中因为想根据用户ip来做一些友好的提示,所以在网上找了个免费的ip查询地址 http://ip.taobao.com/service/getIpInfo.php?ip= 虽然说淘宝的这个地址会 ...
- laya3d 文件格式
先认识下laya3d的一些文件 导出文件说明: ls --- 场景文件: Json文件,包含场景中所有节点的数据信息,包含光照贴图信息 ...