霍夫曼编码c++实现
来源:互联网 发布:淘宝代运营公司的套路 编辑:程序博客网 时间:2024/06/06 02:19
一、霍夫曼编码的原理:
在数据通信时,可以用0,1码的不同排列来表示字符。例如给定一段报文CAST CAST SAT AT A TASA
,在报文中出现的字符集合是{C,A,S,T},各个字符出现的频度是{2,7,4,5}。若给每个字符一个等
长的二进制表示,例如 C:00 A:01 S:10 T:11,则所发的报文将是00011011 00011011 100111 0111 01 11011001,
共计(2+7+5+4)*2=36个码。若按字符出现的频度不同给予不同长度的编码,出现频度较大的字符采用
为数较少的编码,出现频度较小的字符采用位书较多的编码,可以是报文的码数降到最小,这就是所谓的最小
冗余编码问题。霍夫曼编码就能实现这种最小冗余编码。上例中按字符出现的频度进行编码,A:0 T:10 S:110
C:111,则最终的报文只有35个码,节省了传输中使用的单元。
二、核心算法:
一般情况下,霍夫曼编码的工作主要分为两步。第一步是准备工作,对于需要编码的字符(一般存在于文件里)
进行扫描,统计每个字符出现的频次,得到一个整数数组。第二步根据这个频次数组构造一棵霍夫曼树,这一步
是霍夫曼编码的核心内容。第三步,再次扫描一遍待编码的字符,对每个字符,在霍夫曼树里搜索该字符,得到它的编码。
用到的主要数据结构包括:最小堆、二叉树和栈。
算法1:构造霍夫曼树 //////////////////////
输入:频次数组weights[]
输出:频次的霍夫曼树(是一种二叉树)
过程:
1 扫描频次数组weights
针对每个weights[i],构造一个单节点二叉树,插入最小堆中;
2 设weights长度为n,循环n-1次
每次循环都选择二叉树里根的值较小的两棵进行合并,新生成的树
的根的值=旧的两棵树根的值的和,旧的被合并的两棵二叉树被从
最小堆里删除,新合并生成的二叉树插入到最小堆里;
3 最后最小堆里只剩下一棵二叉树,它就是要求的霍夫曼树
算法2:编码算法 //////////////////////////
//从树根开始在HFTree里查找w,向左走记为0
//向右走记为0,最终的01串就是w的编码。
//算法思想类似于二叉树的非递归遍历算法,
//利用栈来存放上一个树节点的信息,
输入:霍夫曼树HFTree,待编码的权值w
输出:编码字符串 str
过程:
1 声明遍历树节点的变量currnode并初始化为HFTree的根节点,
声明遍历时要用的栈stck
2 while( currnode不为空 or stck不为空)
{
访问currnode->data后,将currnode入栈,currnode指向它的左子树,
一直往左走,直到左子树为空;
currnode指向空时,退栈,并让currnode指向当前节点的右孩子;
}
三、算法实现:
算法1:构造霍夫曼树 //////////////////////
//根据权重生成霍夫曼树
//weight 权重数组
//n 权重数组长度
//NewTree 新生成的霍夫曼树
void createHFMTree(int* weights,int n,BinaryTree<int>& NewTree)
{
//初始化堆
MinHeap<BinaryTree<int> > heap(n);
int i=0;
for(;i<n;i++){
heap.Insert(BinaryTree<int>(weights[i]));
}
//选择堆中根数值较小的两棵树,组成一棵新树然后插入堆里,并把原来的两棵树从堆里删除
BinaryTree<int> tree1;
BinaryTree<int> tree2;
i=0;
for(;i<n-1;i++){
if(heap.RemoveMin(tree1)==0){
cout<<"error in createHFMTree--tree1/n";
exit(0);
}
if(heap.RemoveMin(tree2)==0){
cout<<"error in createHFMTree--tree2/n";
exit(0);
}
heap.Insert(BinaryTree<int>(tree1,tree2));
}
if(heap.RemoveMin(NewTree)==0){ //返回最终的霍夫曼树
cout<<"error in createHFMTree--NewTree/n";
exit(0);
}
}
算法2:编码算法 //////////////////////////
//编码
//value 代编码的权值
//tree 霍夫曼树
//code 编码结果(01串)
bool Coding(int value,const BinaryTree<int>& tree,char* code)
{
BinTreeNode<int>* currnode=tree.GetRoot(); /遍历整个树,指向每一个节点
stack<BinTreeNode<int>* > stck; //遍历树时,存放树节点指针的栈
int index_code=0; //结果数组的栈顶
while(currnode!=NULL || !stck.empty()){
//访问currnode->data后,将currnode入栈,遍历左子树
while(currnode!=NULL){
//cout<<code<<endl;
//若数值与value相同,则返回true
if(value==currnode->GetData())
return true;
stck.push(currnode); //currnode入栈
currnode=currnode->GetLeft(); //currnode指向它的右孩子
if(currnode!=NULL)
code[index_code++]='0'; //入栈,栈顶加1
}
//currnode指向空时,退栈,并让currnode指向当前节点的右孩子
if(!stck.empty()){
currnode=stck.top();
stck.pop();
currnode=currnode->GetRight();
if(currnode!=NULL){
index_code--; //出栈
code[index_code++]='1'; //入栈,栈顶加1
}
}
}
return false;
}
四、问题与思考:
参考文献:《数据结构》清华大学出版社 殷人昆等
- 霍夫曼编码的C语言实现
- Huffman编码C实现
- BASE64编码 C实现
- c 实现哈夫曼编码
- C 实现 哈夫曼编码
- c语言实现哈夫曼编码
- c程序实现香农编码
- C语言实现Base64编码
- C语言实现Base64编码
- 哈弗曼编码C语言实现
- c语言实现哈夫曼编码
- C语言实现哈夫曼编码
- 行程编码c语言实现
- C语言实现base64编码
- 哈夫曼编码(C实现)
- C语言实现哈夫曼编码
- C语言实现base64编码
- 赫夫曼编码C语言实现
- 多少年后能实现互联网个人ID网络认证体系
- 快考试了
- 【编程游戏】贺岁放礼花。(点燃续帖1-143楼KiteGirl的焰火)
- 2009的第一天
- 女生朋友送什么好呢?
- 霍夫曼编码c++实现
- (java)数据库连接池
- Axure RP Pro - 相关问题 - 在不同工程之间使用masters主控文档
- 【编程游戏】贺岁放礼花。(点燃续帖1-145楼KiteGirl的焰火)
- java连接常用数据库
- RedHat Linux安装bugzilla 3.2
- 测试ActionForm注册类型自动转换
- Axure RP Pro - 相关问题 - 原型中切换页面时会闪一下
- Windows消息大全使用详解API