霍夫曼压缩算法概念解析

霍夫曼压缩算法概述 霍夫曼压缩算法的主要思想是用较少的比特表示出现频率较高的字符,用较多的比特表示出现频率较低的字符。如下图所示,
霍夫曼压缩算法实现 ①读入完整的输入流,并转化为字符数组。
②计算每个字符出现的次数
③构建huffman树
④构建编译表
⑤将单词查找树编码成比特输出串并写入到输出流
⑥将单词总数编码成比特输出串并写入到输出流
⑦使用编译表翻译每个输入字符
12345678
霍夫曼压缩算法节点的表示 private static final int r = 256; //字符为ascii表示
private static class node implements comparable《node》 {
private final char ch;
private final int freq;
private final node left, right;
public node(char ch, int freq, node left, node right) {
this.freq = freq;
this.ch = ch;
this.left = left;
this.right = right;
}
private boolean isleaf() {
return left == null && right == null;
}
@override
public int compareto(node that) {
return this.freq - that.freq;
}
}
123456789101112131415161718192021222324252627
构建huffman单词查找树 构建初始有一堆没有父节点的节点,将它们放到最小队列中,这样对头总是freq为最小的那个节点。
从队列中找到freq最小的两个节点,创建一个它们的父节点,将三个节点归并成一个大节点,接着放入队列中,
循环往复直至队列中只剩一个节点。
/**
* @param freq 字符出现的次数
* @return
*/
private static node buildtrie(char[] freq) {
minpq《node》 pq = new minpq《node》();
//初始化多个将构成一颗huffman树的结点
for (char i = 0; i 《 r; i++) {
if (freq[i] 》 0) pq.insert(new node(i, freq[i], null, null));
}
// special case in case there is only one character with a nonzero frequency
if (pq.size() == 1) {
if (freq[‘\0’] == 0) pq.insert(new node(‘\0’, 0, null, null));
else pq.insert(new node(‘\1’, 0, null, null));
}
//归并两个小树
while (pq.size() 》 1) {
node left = pq.delmin();
node right = pq.delmin();
node parent = new node(‘\0’, left.freq + right.freq, left, right); //创建连接子树的中间结点
pq.insert(parent);
}
return pq.delmin();
}123456789101112131415161718192021222324252627282930
将huffman单词查找树转化成字节流写到压缩文件中 做如下规定:
中间结点写0;叶子结点写1,并在后面写结点上的字符。
/**
* 将单词查找树编码成比特输出串并写入到输出流
* 用前序遍历
*/
private static void writetrie(node x) {
if (x.isleaf()) {
binarystdout.write(true);
binarystdout.write(x.ch);
return;
}
binarystdout.write(false);
writetrie(x.left);
writetrie(x.right);
}
12345678910111213141516
将压缩文件中字节流转化为huffman单词查找树 按写入时的规定解析字节流。
/**
* 读比特流,得出一颗单词查找树
*/
private static node readtrie() {
if (binarystdin.readboolean()) { //读到1,说明是叶子结点
return new node(binarystdin.readchar(), 0, null, null);
}
//读到的是0,说明是中间结点,需要递归直到读到1为止
node left = readtrie();
node right = readtrie();
return new node(‘\0’, 0, left, right);
}
123456789101112131415
构建编译表 构建编译表st,索引为字符,值为路径(比特字符串)。
根据这张表,可以将源文件中的某个字符,压缩为更少bit表示的huffman树上的路径。
private static void buildcode(string[] st, node x, string s) {
if (!x.isleaf()) {
buildcode(st, x.left, s + “0”);
buildcode(st, x.right, s + “1”);
} else {
st[x.ch] = s;
}
}
12345678910
压缩 /**
* 从输入流中读字节流,并将压缩后的结果写入输出流
*/
private static void compress() {
//①读入完整的输入流,并转化为字符数组
string s = binarystdin.readstring();
char[] input = s.tochararray();
//②计算每个字符出现的次数,没有出现的就为0
char[] freq = new char[r];
for (int i = 0; i 《 input.length; i++) {
freq[input[i]]++;
}
//③构建huffman树
node root = buildtrie(freq);
//④构建编译表,将输入中的每个char值与一个比特字符串(即huffman树上路径)相关联
string st[] = new string[r];
buildcode(st, root, “”);
//⑤将单词查找树编码成比特输出串并写入到输出流
writetrie(root);
//⑥将单词总数编码成比特输出串并写入到输出流
binarystdout.write(input.length);
//⑦使用编译表翻译每个输入字符
for (int i = 0; i 《 input.length; i++) {
string code = st[input[i]]; //code表示huffman单词查找数上的路径
for (int j = 0; j 《 code.length(); j++) { //要一位一位地输出
if (code.charat(j) == ‘1’) {
binarystdout.write(true);
} else {
binarystdout.write(false);
}
}
}
binarystdout.close();
}
12345678910111213141516171819202122232425262728293031323334353637383940414243444546
### 解压
/**
* 解压
* 读取压缩文件的比特流,
* 将比特流对应为路径在单词查找树上找,将找到的结点中的字符写出
*/
private static void expand() {
node root = readtrie();
int n = binarystdin.readint(); //读出存在压缩文件中的字符串长度
for (int i = 0; i 《 n; i++) { //找出源文件中每个字符
node x = root;
while (!x.isleaf()) { //遍历,知道叶子结点
if (binarystdin.readboolean()) {
x = x.right;
} else {
x = x.left;
}
}
binarystdout.write(x.ch);
}
binarystdout.close();
}

关于最优的电源管理架构的了解分析
高通骁龙660被OPPO R11独占2个月,或将与6月份开卖
PCB布线模拟电路与数字电路部分
ADI推出最新全面的无线传感器开发套件
简单分享近场探头的用途
霍夫曼压缩算法概念解析
Nexperia | 扩展用于汽车以太网的ESD保护解决方案产品组合
健身房中的智能无脂镜,运动数据实现可视化
82届中国电子展展商巡礼:联华电子
绘制与识读电气控制线路原理图遵循的原则
SCHURTER推出新款共模扼流圈
什么是启动继电器 怎么判断启动继电器的好坏
华为新品发布会邀请函曝光,将会正式上线华为Mate X
聚焦 | 美国软件巨头北京研发中心裁员,N+6补偿方案是“良心价”吗?
油库、加油站、危化企业防雷工程应用方案
近年来自动驾驶事故频发,拒绝购买自动驾驶汽车的美国人数量增加
智能监控领域特征识别有什么发展
低压差线性稳压器的稳压原理介绍
重庆首届中国国际智能产业博览会期间举行
【风火轮YY3568开发板免费体验】第一章:开发环境搭建,系统替换为原生Linux