作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4096079.html

使用优先队列实现,需要注意以下几点:

1.在使用priority_queue时,内部需要存储哈夫曼树节点的指针,而不能是节点。因为构建哈夫曼树时,需要把其左右指针指向孩子,而如果储存的是节点,那么孩子的地址是会改变的。同理节点应当使用new在内存中开辟,而不能使用vector,原因是vector在数组大小为2整数次幂时,大小会倍增,开辟新数组并把老数组的数字copy过去,从而也会导致地址变化。

2.优先队列对指针的排列,需要额外写一个比较函数来比较指针指向的节点的大小。bool operator () (wcnode * node1, wcnode * node2) return node1->lessthan(node2);并在定义优先队列时使用这种方法:    priority_queue <wcnode*, vector<wcnode*>, compare> 第一个参数是节点类型,第二个参数是优先队列的储存结构,第三个参数是比较函数。

3.C++在写入文件时,由于只能按字节写入,因此需要把8个bit位转化为一个字节,最后不足8位用0补齐,并记录文件总bit数,便于解码。然后写入文件。另写入二进制文件可以使用ofstream out("output.txt",std::ofstream::binary);

4.哈夫曼编码信息包括每种字符的映射,和该文件的总bit数。

其代码如下:

 #include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <fstream>
#include <queue>
#include <map>
#include <vector>
using namespace std;
class compare; class wcnode
{
public:
friend class compare;
char word;
int count;
wcnode* left;
wcnode* right;
bool lessthan (const wcnode *w)const
{
return count > w->count;
}
wcnode(char w='\0', int c=, wcnode* l=NULL, wcnode * r=NULL)
{
word = w; count = c; left = l; right = r;
}
}; class compare
{
public:
bool operator () (wcnode * node1, wcnode * node2)
{
return node1->lessthan(node2);
}
}; void preorder(wcnode *head, vector<bool> rec, map<char, vector<bool> > & res)
{
if( head->left == NULL && head->right == NULL )
{
res[head->word] = rec;
return;
}
vector<bool> l = rec;
l.push_back();
vector<bool> r = rec;
r.push_back();
if(head->left != NULL) preorder(head->left, l, res);
if(head->right != NULL) preorder(head->right, r, res);
}
map<char, vector<bool> > encode(map<char, int> &wordcount)
{
map<char, vector<bool> > res;
priority_queue <wcnode*, vector<wcnode*>, compare> pq;
map<char, int>::iterator t;
wcnode *tmp;
wcnode *t1, *t2, *t3; for( t = wordcount.begin() ; t != wordcount.end() ; t++ )
{
tmp = new wcnode();
tmp->word = t->first;
tmp->count = t->second;
pq.push(tmp);
}
while( pq.size() > )
{
t1 = pq.top();
pq.pop();
t2 = pq.top();
pq.pop();
t3 = new wcnode();
t3->count = t1->count + t2->count;
t3->left = t1;
t3->right = t2;
pq.push(t3);
}
wcnode *huffmanhead = pq.top();
vector<bool> rec;
preorder(huffmanhead, rec, res);
map<char, vector<bool> >::iterator it;
for( it = res.begin() ; it != res.end() ; it++ )
{
cout<<it->first<<":";
for( int i = ; i < it->second.size() ; i++ )
{
cout<<it->second[i];
}
cout<<", ";
}
return res;
} void output(string s, string passage, map<char, vector<bool> > res)
{
ofstream out(s.c_str());
vector<bool> bit;
for( int i = ; i < passage.size() ; i++ )
{
vector<bool> tmp = res[passage[i]];
for( int i = ; i < tmp.size(); i++ )
{
bit.push_back(tmp[i]);
}
}
char outputchar = ;
for( int i = ; i < bit.size() ; i++ )
{
if( i % == )
{
out.write(&outputchar, sizeof(outputchar));
outputchar = ;
}
outputchar = outputchar + bit[i];
outputchar = outputchar * ;
}
if( outputchar != )
{
out.write(&outputchar, sizeof(outputchar));
}
out.close();
}
int main(int argc, char *argv[])
{
char tmp;
ifstream in("Aesop_Fables.txt");
map <char, int> wordcount;
map <char, vector<bool> > res;
string passage;
while( in.get(tmp) )
{
passage += tmp;
if( wordcount.count(tmp) == )
{
wordcount[tmp] = ;
}
else
{
wordcount[tmp]++;
}
}
res = encode(wordcount);
output("outAesop.txt", passage, res);
in.close();
}

 

Huffman Coding 哈夫曼编码的更多相关文章

  1. Huffuman Coding (哈夫曼编码)

    哈夫曼编码(Huffman Coding),又称霍夫曼编码,是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种.Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头 ...

  2. 哈夫曼(Huffman)树+哈夫曼编码

    前天acm实验课,老师教了几种排序,抓的一套题上有一个哈夫曼树的题,正好之前离散数学也讲过哈夫曼树,这里我就结合课本,整理一篇关于哈夫曼树的博客. 主要摘自https://www.cnblogs.co ...

  3. 霍夫曼编码(Huffman Coding)

    霍夫曼编码(Huffman Coding)是一种编码方法,霍夫曼编码是可变字长编码(VLC)的一种. 霍夫曼编码使用变长编码表对源符号(如文件中的一个字母)进行编码,其中变长编码表是通过一种评估来源符 ...

  4. 哈夫曼编码(Huffman coding)的那些事,(编码技术介绍和程序实现)

    前言 哈夫曼编码(Huffman coding)是一种可变长的前缀码.哈夫曼编码使用的算法是David A. Huffman还是在MIT的学生时提出的,并且在1952年发表了名为<A Metho ...

  5. 哈夫曼编码的理解(Huffman Coding)

    哈夫曼编码(Huffman Coding),又称霍夫曼编码,是一种编码方式,可变字长编码(VLC)的一种.Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长度最 ...

  6. 赫夫曼\哈夫曼\霍夫曼编码 (Huffman Tree)

    哈夫曼树 给定n个权值作为n的叶子结点,构造一棵二叉树,若带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree).哈夫曼树是带权路径长度最短的树,权值较大的结点离 ...

  7. 哈夫曼树(Huffman Tree)与哈夫曼编码

    哈夫曼树(Huffman Tree)与哈夫曼编码(Huffman coding)

  8. 哈夫曼(huffman)树和哈夫曼编码

    哈夫曼树 哈夫曼树也叫最优二叉树(哈夫曼树) 问题:什么是哈夫曼树? 例:将学生的百分制成绩转换为五分制成绩:≥90 分: A,80-89分: B,70-79分: C,60-69分: D,<60 ...

  9. (转载)哈夫曼编码(Huffman)

    转载自:click here 1.哈夫曼编码的起源: 哈夫曼编码是 1952 年由 David A. Huffman 提出的一种无损数据压缩的编码算法.哈夫曼编码先统计出每种字母在字符串里出现的频率, ...

随机推荐

  1. 将某个组中的账户移动到新的OU下

    将某个组中的账户移动到新的OU下 #定义组名 $groupname = "testg" #定义新的OU名称 $newou = "OU=oo,OU=Admins,dc=dd ...

  2. 【07】为多态基类声明virtual析构方法

    1.考虑下面的需要,需要一个工厂方法.工厂方法的规则是:在堆上分配一个子类对象,并返回父类指针.使用完毕,delete父类指针.如果父类的析构方法不是virtual,将直接调用父类的析构方法,导致局部 ...

  3. Android 获取信号强度

    大 家看到标题就明白了,我们有的时候在电梯里,有时有的电话有信号,有时有的电话没有信号,这个是非常闹心的,要是我们能监听一下我们自己手机信号的强度就 好了.这样,当我们在等重要的人士的电话,不至于接不 ...

  4. sizeof运算符

    sizeof运算符返回一条表达式或一个类型名字所占的字节数.sizeof运算符满足右结合律,其所得的值是一个size_t类型的常量表达式.运算符的运算对象有两种形式: sizeof(type) siz ...

  5. MySQL(16):Select-union(联合查询)

    1. Select-union(联合查询) union用于把来自许多SELECT语句的结果组合到一个结果集合中. 用法: SELECT ...UNION [ALL | DISTINCT]SELECT ...

  6. oracle数据库管理员简介、导入数据与导出数据

    数据库管理员: sys和system的权限区别:sys:所有oracle的数据字典的基表和视图都存放在sys用户中,这些基表和视图对于oracle的运行时至关重要的,由数据库 自己维护,任何用户都不能 ...

  7. Android_Spinner_example

    xml数据: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns ...

  8. ios定制中间突出的tabBar

    我觉得有两个思路,一个是自己写tabBar  通过自定义实现,缺点呢就是比较麻烦,优点就是代码比较清楚,而且比较稳定. 另一个思路就是写个大按钮加在tabBar上 通过监听tabitem的点击来实现相 ...

  9. 《Mysql 公司职员学习篇》 第三章 小A的疑问

    第三章 小A的疑问  ---- 数据类型和自增列 小A拿着鸡腿,回到了房间里面,咬了一嘴油,说:"我有2个疑问,在Excell里面,像列PetAge(宠物年龄)这样的数字,我一般会设置成数值 ...

  10. Pyhont 网络编程【第一篇】初始Socket网络套接字

    一.什么是socket: Socket 别名 “网络套接字”,指网络通信链句柄 其实就是一堆网络信息(ip+端口) 建立起的链接称之为socket,Socket的英文原义是“孔”或“插座”,用来实现不 ...