huffman 编码
huffman压缩是一种压缩算法,其中经典的部分就是根据字符出现的频率建立huffman树,然后根据huffman树的构建结果标示每个字符。huffman编码也称为前缀编码,就是每个字符的表示形式不是另一个字符表示的前缀。如果学过c语言版本的数据结构的话,那么会知道其上面的算法的时间复杂度是O(N^2), 也算是比较复杂的,那么首先贴上这个版本算法的代码:
#include<iostream>
#include<string>
using namespace std; typedef struct huffman_node_s {
int weight;
int parent;
int lchild;
int rchild;
}huffman_node_t, *HuffmanTree; typedef char** HuffmanCode; void select(HuffmanTree ht, int n, int* s1, int* s2) {
int i;
int temp;
*s1 = *s2 = 0;
for (i = 1; i <= n; i++) {
if (0 == ht[i].parent) {
if (0 == *s1 && 0 == *s2) {
*s1 = i;
continue;
} else if (0 == *s2) {
*s2 = i;
if (ht[*s1].weight > ht[*s2].weight) {
temp = *s1, *s1 = *s2, *s2 = temp;
}
continue;
}
if (ht[i].weight < ht[*s1].weight && ht[i].weight < ht[*s2].weight) {
*s2 = *s1;
*s1 = i;
} else if (ht[i].weight > ht[*s1].weight && ht[i].weight < ht[*s2].weight) {
*s2 = i;
}
}
}
} void HuffmanEncode(HuffmanTree* ht, HuffmanCode* hc, int* weight, int n) {
int i, start;
int s1, s2;
int c, f;
int m = 2 * n - 1;
*ht = (huffman_node_t*)malloc((m + 1) * sizeof(huffman_node_t));
for (i = 1; i <= m; i++) {
if (i <= n) {
(*ht)[i].weight = weight[i - 1];
} else {
(*ht)[i].weight = 0;
}
(*ht)[i].parent = 0;
(*ht)[i].lchild = 0;
(*ht)[i].rchild = 0;
}
for (i = n + 1; i <= m; i++) {
select(*ht, i - 1, &s1, &s2);
(*ht)[i].lchild = s1;
(*ht)[i].rchild = s2;
(*ht)[i].weight = (*ht)[s1].weight + (*ht)[s2].weight;
(*ht)[s1].parent = (*ht)[s2].parent = i;
}
*hc = (char**)malloc((n + 1) * sizeof(char*));
char* temp = (char*)malloc(n * sizeof(char));
for (i = 1; i <= n; i++) {
temp[n - 1] = '\0';
start = n - 1;
for (c = i, f = (*ht)[i].parent; f != 0; c = f, f = (*ht)[f].parent) {
if (c == (*ht)[f].lchild)
temp[--start] = '0';
else
temp[--start] = '1';
}
(*hc)[i] = (char*)malloc(n - start);
strcpy((*hc)[i], temp + start);
}
} int main(int argc, char* argv[]) {
int weight[] = {5, 29, 7, 8, 14, 23, 3, 11};
int length = sizeof(weight) / sizeof(int);
HuffmanTree ht = NULL;
HuffmanCode hc = NULL;
HuffmanEncode(&ht, &hc, weight, length);
int i;
for (i = 1; i <= length; i++)
cout << hc[i] << endl;
for (i = 1; i <= length; i++)
free(hc[i]);
free(hc);
cin.get();
return 0;
}
还有另外一种算法,就是用爽队列的形式,可以把时间复杂度降到O(N*logN),算法的核心思想是:
1, 建立两个空的队列
2,为每一个字符建立一个节点,并按照字符出现的频率以非递减的方式放入第一个队列
3,每步要找出出现频率最小的两个字符,那么可以根据以下方法进行查找:
a,如果第二个队列为空,那么使第一个队列的头结点出列
b,如果第一个队列为空,那么使第二个队列的头结点出列
c,如果两个队列都不为空,那比较两个队列头结点字符出现的频率,使出现频率较小的头结点出列
4,创建一个新的临时节点,它的频率是第三步骤中出列两个节点所包含的字符的频率之和,然后将临时节点压入第二个队列,当第一个队列中不包含元素节点而第二个队列中只有一个元素节点的时候,停止算法,下面给出代码:
#include<iostream>
#include<string>
using namespace std; typedef struct queue_node_s {
char data;
int frequent;
struct queue_node_s* lchild;
struct queue_node_s* rchild;
}queue_node_t; typedef struct queue_s {
int front, rear;
int capcity;
queue_node_t** arr;
}queue_t; queue_node_t* createNode(char data, int frequent) {
queue_node_t* node = (queue_node_t*)malloc(sizeof(queue_node_t));
node->data = data;
node->frequent = frequent;
node->lchild = NULL;
node->rchild = NULL;
return node;
} queue_t* createQueue(int size) {
queue_t* queue = (queue_t*)malloc(sizeof(queue_t));
queue->capcity = size;
queue->front = queue->rear = -1;
queue->arr = (queue_node_t**)malloc(size * sizeof(queue_node_t));
if (NULL == queue->arr) {
free(queue);
return NULL;
}
return queue;
} bool isQueueEmpty(queue_t* queue) {
if (-1 == queue->front && -1 == queue->rear)
return true;
return false;
} bool isContainOne(queue_t* queue) {
if (queue->rear == queue->front && queue->front != -1)
return true;
return false;
} bool isQueueFull(queue_t* queue) {
return queue->rear == queue->capcity - 1;
} void enQueue(queue_t* queue, queue_node_t* item) {
if (isQueueFull(queue))
return;
queue->arr[++queue->rear] = item;
if (-1 == queue->front)
queue->front++;
} queue_node_t* deQueue(queue_t* queue) {
if (isQueueEmpty(queue))
return NULL;
queue_node_t* temp = queue->arr[queue->front];
if (queue->front == queue->rear)
queue->front = queue->rear = -1;
else
queue->front++;
return temp;
} queue_node_t* getFront(queue_t* queue) {
if (isQueueEmpty(queue))
return NULL;
return queue->arr[queue->front];
} queue_node_t* findMin(queue_t* queueOne, queue_t* queueTwo) {
if (isQueueEmpty(queueOne))
return deQueue(queueTwo);
if (isQueueEmpty(queueTwo))
return deQueue(queueOne);
if (getFront(queueOne)->frequent < getFront(queueTwo)->frequent)
return deQueue(queueOne);
return deQueue(queueTwo);
} void printArr(char* arr, int n) {
int i;
for (i = 0; i < n; i++)
printf("%c", arr[i]);
cout << endl;
} bool isLeaf(queue_node_t* node) {
if (NULL == node->lchild && NULL == node->rchild)
return true;
return false;
} queue_node_t* buildHuffmanTree(char* data, int* frequents, int size) {
queue_node_t* lchild;
queue_node_t* rchild;
queue_node_t* top;
queue_t* queueOne = createQueue(size);
queue_t* queueTwo = createQueue(size);
int i;
for (i = 0; i < size; i++)
enQueue(queueOne, createNode(data[i], frequents[i]));
while (!(isQueueEmpty(queueOne) && isContainOne(queueTwo))) {
lchild = findMin(queueOne, queueTwo);
rchild = findMin(queueOne, queueTwo);
top = createNode('$', lchild->frequent + rchild->frequent);
top->lchild = lchild;
top->rchild = rchild;
enQueue(queueTwo, top);
}
return deQueue(queueTwo);
} void printCodes(queue_node_t* node, char* arr, int top) {
if (node->lchild) {
arr[top] = '0';
printCodes(node->lchild, arr, top + 1);
}
if (node->rchild) {
arr[top] = '1';
printCodes(node->rchild, arr, top + 1);
}
if (isLeaf(node)) {
printf("%c:", node->data);
printArr(arr, top);
}
} void HuffmanCodes(char* data, int* frequents, int size) {
queue_node_t* root = buildHuffmanTree(data, frequents, size);
char* arr = (char*)malloc(size * sizeof(char));
int top = 0;
printCodes(root, arr, top);
free(arr);
} int main(int argc, char* argv[]) {
char data[] = {'a', 'b', 'c', 'd', 'e', 'f'};
int freq[] = {5, 9, 12, 13, 16, 45};
int size = sizeof(data) / sizeof(data[0]);
HuffmanCodes(data, freq, size);
cin.get();
return 0;
}
huffman 编码的更多相关文章
- [老文章搬家] 关于 Huffman 编码
按:去年接手一个项目,涉及到一个一个叫做Mxpeg的非主流视频编码格式,编解码器是厂商以源代码形式提供的,但是可能代码写的不算健壮,以至于我们tcp直连设备很正常,但是经过一个UDP数据分发服务器之后 ...
- Huffman编码
#define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <cstdio> #include <cstri ...
- 【数据压缩】Huffman编码
1. 压缩编码概述 数据压缩在日常生活极为常见,平常所用到jpg.mp3均采用数据压缩(采用Huffman编码)以减少占用空间.编码\(C\)是指从字符空间\(A\)到码字表\(X\)的映射.数据压缩 ...
- 优先队列求解Huffman编码 c++
优先队列小析 优先队列的模板: template <class T, class Container = vector<T>,class Compare = less< ...
- Huffman编码实现电文的转码与译码
//first thing:thanks to my teacher---chenrong Dalian Maritime university /* 构造Huffman Tree思路: ( ...
- 基于二叉树和数组实现限制长度的最优Huffman编码
具体介绍详见上篇博客:基于二叉树和双向链表实现限制长度的最优Huffman编码 基于数组和基于链表的实现方式在效率上有明显区别: 编码256个符号,符号权重为1...256,限制长度为16,循环编码1 ...
- uvalive 2088 - Entropy(huffman编码)
题目连接:2088 - Entropy 题目大意:给出一个字符串, 包括A~Z和_, 现在要根据字符出现的频率为他们进行编码,要求编码后字节最小, 然后输出字符均为8字节表示时的总字节数, 以及最小的 ...
- Jcompress: 一款基于huffman编码和最小堆的压缩、解压缩小程序
前言 最近基于huffman编码和最小堆排序算法实现了一个压缩.解压缩的小程序.其源代码已经上传到github上面: Jcompress下载地址 .在本人的github上面有一个叫Utility的re ...
- DS二叉树--Huffman编码与解码
题目描述 1.问题描述 给定n个字符及其对应的权值,构造Huffman树,并进行huffman编码和译(解)码. 构造Huffman树时,要求左子树根的权值小于.等于右子树根的权值. 进行Huffma ...
随机推荐
- 【BZOJ1031】[JSOI2007]字符加密Cipher 后缀数组
[BZOJ1031][JSOI2007]字符加密Cipher Description 喜欢钻研问题的JS同学,最近又迷上了对加密方法的思考.一天,他突然想出了一种他认为是终极的加密办法 :把需要加密的 ...
- SQL 通配符
在搜索数据库中的数据时,SQL 通配符可以替代一个或多个字符.SQL 通配符必须与 LIKE 运算符一起使用,必须放在引号内. 在 SQL 中,可使用以下通配符: %:替代一个或多个字符. _:仅替代 ...
- [破解] DRM-内容数据版权加密保护技术学习(上):视频文件打包实现
1. DRM介绍: DRM,英文全称Digital Rights Management, 可以翻译为:内容数字版权加密保护技术. DRM技术的工作原理是,首先建立数字节目授权中心.编码压缩后的数字节目 ...
- 设计模式入门之职责链模式Chain Of Responsibility
//职责链模式:使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系.将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止. //实例:申请费用的功能,不同金额的费 ...
- 面向对象3-this的用法
1.当有定时器时 this会指向window <script type="text/javascript"> function Aaa(){ var _this=thi ...
- Oracle SQL函数之转换函数To_char汇总
TO_CHAR(x[[,c2],C3])[功能]将日期或数据转换为char数据类型[参数]x是一个date或number数据类型.c2为格式参数c3为NLS设置参数如果x为日期nlsparm=NLS_ ...
- mysql跟踪提交的SQL语句
http://www.cnblogs.com/wuyifu/p/3328024.html
- Java使用默认浏览器打开指定URL
直接贴代码: 方法一: Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler http://www.baidu.co ...
- <audio>使用2
1.属性测试 <!--显示控件--> <audio src="../images/wind.mp3" id="audioOne" contro ...
- Json.Net介绍及实例
本系列教程假设读者已经对Json有一定的了解,关于Json在这里不多说.本系列教程希望能对读者开发涉及到Json的.Net项目有一定的帮助.本系列教程是根据官方文档资料和自己项目应用汇总而成.如果觉得 ...