哈夫曼编码 (Huffman code)的实现,压缩、解压缩
2015-08-05 16:43
627 查看
此程序首先扫描一遍输入文件并统计各个字符的出现次数,然后对结果排序,再由此构造Huffman树,然后对树进行一个遍历,并把各个字符的Huffman编码存到一个hash表中,所谓hash表就是建立一个string数组,数组下标用字符的ASCII码表示,数组内容用此字符对应的Huffman编码表示,例如,a:11,则 hash[‘a’] = “11”;
然后重新对文件进行一遍扫描,根据hash表进行压缩,解压根据Huffman树来进行。存到文件是按8位存的,这个地方费了不少力气。
要验证效果,可以在程序目录下建立“ huffman.in” 文本文件,进行程序后生成的 huffman.bin是压缩后的二进制文件,可以用UE看其内容,生成的huffman.out为解压后的文件,内容和原文件一样。
对中文也可压缩。
[cpp] view plaincopy
/* Huffman Code */
/Huffman Tree’s Node/
struct TreeNode{
int value;
int alpha;
string code;
TreeNode * lChild;
TreeNode * rChild;
TreeNode(){ value = 0; alpha = 0; lChild = rChild = NULL; code=”“;} //构造函数
};
/链表结点,辅助构造Huffman树/
struct ListNode{
TreeNode huffNode;
ListNode * child;
ListNode(){ child = NULL;} //构造函数
};
//保存输入文件的统计信息,hash表
struct hashTable{
int value;
int alpha;
hashTable(){alpha=0; value=0;}
}Ascii[CharCount];
//qsort的排序函数
int Comp(const void *a, const void *b)
{
return (int )a - (int )b;
}
TreeNode * CreateHuffmanTree(hashTable ascii[])
{
/初始化建立二叉树森林,每个树只有一个结点,并把这些森林串到一个链表中/
ListNode * root = new ListNode;
ListNode * next = root; //root指向第一个节点,此节点有信息
}
/字符-Huffman码表/
string charHuffmanTable[CharCount];
/字符串栈,用来在遍历Huffman树时得到Huffman编码/
string stack;
/树的前序遍历/
void preorder(TreeNode * root)
{
// if(root == NULL)
// {
// stack.erase(stack.length()-2);
// return;
// }
// else
// {
//printf(“%c %d\n”, root->alpha, root->value);
if(root->lChild == NULL && root->rChild == NULL)
{
charHuffmanTable[root->alpha] = stack;
stack.erase(stack.length()-1);
return;
}
stack.append(“0”);
preorder(root->lChild);
// }
}
//传进来一个”10101001”的字符串,返回一个对应的ASCII字符
unsigned char StrToBin(string str)
{
int a = atoi(str.c_str());
int b = 1;
int ans = 0;
while(a != 0)
{
ans += a%10 * b;
b *= 2;
a /= 10;
}
return (unsigned char)ans;
}
//把unsigned char类型转换为2进制字符串
string BinToStr(unsigned char c)
{
string ans;
while(c != 0)
{
ans.insert(ans.begin(), unsigned char(c%2 + ‘0’));
c /= 2;
}
}
/[b]**************************************************************[/b]/
/译码模块,返回译出的字符,删除string中已经用过的串 /
/[b]**************************************************************[/b]/
char decode(TreeNode * root, string & code)
{
for(int i=0; i
然后重新对文件进行一遍扫描,根据hash表进行压缩,解压根据Huffman树来进行。存到文件是按8位存的,这个地方费了不少力气。
要验证效果,可以在程序目录下建立“ huffman.in” 文本文件,进行程序后生成的 huffman.bin是压缩后的二进制文件,可以用UE看其内容,生成的huffman.out为解压后的文件,内容和原文件一样。
对中文也可压缩。
[cpp] view plaincopy
/* Huffman Code */
include
include
include
include
include
include
include
define CharCount 256
using namespace std;/Huffman Tree’s Node/
struct TreeNode{
int value;
int alpha;
string code;
TreeNode * lChild;
TreeNode * rChild;
TreeNode(){ value = 0; alpha = 0; lChild = rChild = NULL; code=”“;} //构造函数
};
/链表结点,辅助构造Huffman树/
struct ListNode{
TreeNode huffNode;
ListNode * child;
ListNode(){ child = NULL;} //构造函数
};
//保存输入文件的统计信息,hash表
struct hashTable{
int value;
int alpha;
hashTable(){alpha=0; value=0;}
}Ascii[CharCount];
//qsort的排序函数
int Comp(const void *a, const void *b)
{
return (int )a - (int )b;
}
TreeNode * CreateHuffmanTree(hashTable ascii[])
{
/初始化建立二叉树森林,每个树只有一个结点,并把这些森林串到一个链表中/
ListNode * root = new ListNode;
ListNode * next = root; //root指向第一个节点,此节点有信息
for(int i=0; /*i<127*/; i++) { if(ascii[i].value == 0) continue; next->huffNode.value = ascii[i].value; next->huffNode.alpha = ascii[i].alpha; if(i == CharCount-1) //防止多建一个无用的节点 break; next->child = new ListNode; next = next->child; } //如果森林中的树>1,就继续处理,直到森林(链表)中只有一颗树,这时Huffman树也已建成 while(root->child != NULL) { ListNode * p = new ListNode; /*把新结点的权值设为最小两个结点的权值之和*/ p->huffNode.value = root->huffNode.value + root->child->huffNode.value; /*把新结点中的Huffman节点中的左右子树设置为两个较小节点中的Huffman节点*/ p->huffNode.lChild = &(root->huffNode); p->huffNode.rChild = &(root->child->huffNode); /*从链表中删除最小的两个结点,但是内存不能释放,因为还要用这些节点构造Huffman树*/ root = root->child->child; /*对链表重新排序,即把新建的这个结点插入到合适的位置,使链表的升序不被破坏*/ next = root; ListNode * parent = NULL; while( next != NULL && p->huffNode.value >= next->huffNode.value ) { parent = next; next = next->child; }// find location //insert if(parent == NULL) // Insert into start. { p->child = next; root = p; } else // Insert into middle or end. { p->child = next; parent->child = p; } } return &(root->huffNode);
}
/字符-Huffman码表/
string charHuffmanTable[CharCount];
/字符串栈,用来在遍历Huffman树时得到Huffman编码/
string stack;
/树的前序遍历/
void preorder(TreeNode * root)
{
// if(root == NULL)
// {
// stack.erase(stack.length()-2);
// return;
// }
// else
// {
//printf(“%c %d\n”, root->alpha, root->value);
if(root->lChild == NULL && root->rChild == NULL)
{
charHuffmanTable[root->alpha] = stack;
stack.erase(stack.length()-1);
return;
}
stack.append(“0”);
preorder(root->lChild);
stack.append("1"); preorder(root->rChild); //cout << stack.length() << endl; if(!stack.empty()) stack.erase(stack.length()-1);
// }
}
//传进来一个”10101001”的字符串,返回一个对应的ASCII字符
unsigned char StrToBin(string str)
{
int a = atoi(str.c_str());
int b = 1;
int ans = 0;
while(a != 0)
{
ans += a%10 * b;
b *= 2;
a /= 10;
}
return (unsigned char)ans;
}
//把unsigned char类型转换为2进制字符串
string BinToStr(unsigned char c)
{
string ans;
while(c != 0)
{
ans.insert(ans.begin(), unsigned char(c%2 + ‘0’));
c /= 2;
}
if(ans.length() < 8) { ans.insert(ans.begin(), 8-ans.length(), '0'); } return ans;
}
/[b]**************************************************************[/b]/
/译码模块,返回译出的字符,删除string中已经用过的串 /
/[b]**************************************************************[/b]/
char decode(TreeNode * root, string & code)
{
for(int i=0; i
相关文章推荐
- 栈的实现
- fragmentActivity布局文件报错Error inflating class fragment
- NLP超级初步
- spring 配置文件属性
- CentOS 修改主机名
- JS学习之this关键字
- vs执行程序时提示无法启动程序,系统找不到指定的文件
- 轻松入门学习java入门的常用语言知识
- duilib中,子xml创建自定义控件
- Android.mk简介
- SYN Cookie的原理和实现
- 速度之王 — LZ4压缩算法
- Eclipse+Spring+SpringMVC+Mybatis+Maven+多库配置+resin
- UVa 725----Division(枚举)
- ROS 教程之 vision : 用各种摄像头获取图像
- jq实现切换栏目显示效果
- Android.mk简介<转>
- 被7整除
- Sqlite3中存储类型和数据类型结合文档解析。
- 【Python】【3】Python之——从HelloWorld开始(四则运算,简单函数以及简单模块)