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 ...
随机推荐
- java开发中遇到的问题及解决方法(持续更新)
摘自 http://blog.csdn.net/pony12/article/details/38456261 java开发中遇到的问题及解决方法(持续更新) 工作中,以C/C++开发为主,难免与其他 ...
- 水务新、老营收系统大PK
今天想撩一下咱水务界的大拿——营业收费管理系统. 营业收费 随着城市供水规模的不断扩大及户表改造的深入以及阶梯水价的实行还有移动平台等第三方支付的蓬勃发展,原有的营收软件系统已经不能适应目前水司的管理 ...
- Primes on Interval(二分 + 素数打表)
Primes on Interval Time Limit:1000MS Memory Limit:262144KB 64bit IO Format:%I64d & %I64u ...
- setSingleChoiceItems和setPositiveButton两者触发时期
两者都是对话框中的操作当中 setSingleChoiceItems是在点击对话框中的列表时候被触发,当点击后运行实现的内容 setPositiveButton是在点击完对话框中的确定button时被 ...
- 在Swift中使用遗留的C API
Swift的类型系统的设计目的在于简化我们的生活,为此它强制用户遵守严格的代码规范来达到这一点.毫无疑问这是一件大好事,它鼓励程序员们编写 更好更正确的代码.然而,当Swift与历史遗留的代码库.特别 ...
- Jq合成事件绑定
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- C#中精确计时的一点收获
以下所有代码运行环境:Windows 2003, Intel(R) Core(TM) 2 Duo CPU E8400 @ 3.00GHz 2.99GHz,2.96GB内存 根据综合网上的一些文章,精 ...
- Android应用截图嵌入到真实设备
Device Art Generator 你可以使用 Device Art Generator 方便快捷地将应用截图嵌入到真实设备的效果图中.这样,当用户在你的网站上或其他宣传材料中看到你的应用截图时 ...
- Android url中文编码问题
最近项目遇见一个很奇葩问题,关于URL问题,项目中加载图片,图片的URL含有中文,但是,我的手机可以加载,没问题,同事也都可以,但是测试手机却不可以,加载失败,找到问题,就是URL含有中文问题. 解决 ...
- wampserver php 设置时间
php.ini 查找date.timezone = Europe/Paris 修改成亚洲地区 date.timezone = Asia/Shanghai