首先,根据输入的字符串确定每个字母的频率,也就是权值,然后构造哈夫曼树,进行编码。解码就是从根节点不断往下查找,直到叶节点的过程。看哪个字符与从某序列匹配。
#include <iostream>
#include <map>
#include <queue>
using namespace std;
struct node{ //哈夫曼树的结点
char ch;
int frequent;
node *lchild,*rchild;
node(char c=0,double f=0,node *l=NULL,node *r=NULL):ch(c),frequent(f),lchild(l),rchild(r){} //构造函数
};
struct cmp1{ //比较函数,根据字母出现的频率按从小到大排列
bool operator()(node *&a,node *&b){
return a->frequent > b->frequent;
}
};
node * createTree(string str){ //构造哈夫曼树
map<char,int>charSet;
for(int i=0;i<str.length();i++) //map结构保存字母出现的频次
charSet[str[i]]++;
priority_queue<node*,vector<node*>,cmp1>que; //优先队列,按频次入队
for(map<char,int>::iterator p = charSet.begin();p!=charSet.end();p++){
que.push(new node(p->first,p->second));
}
while(que.size()>1){
node *l = que.top();
que.pop();
node *r = que.top(); //选出权值最小的两个点,然后合并
que.pop();
node * newnode = new node(0,l->frequent+r->frequent,l,r);
que.push(newnode);
}
return que.top(); //返回的是哈夫曼树中的顶层节点
}
void printInfo(const node* tree,string code){
if(tree->lchild == NULL && tree->rchild == NULL){
cout<<tree->ch<<":"<<code<<endl;
return;
}
if(tree->lchild != NULL) printInfo(tree->lchild,code+'0'); //向左走,为0
if(tree->rchild != NULL) printInfo(tree->rchild,code+'1'); //向右走,为1
}
string decode(const node *tree,string str){
string ret = "";
const node *p = tree;
for(int i=0;i<str.length();i++){
p = str[i] == '0'?p->lchild:p->rchild;
if(p->lchild == NULL && p->rchild == NULL){ //看是否到叶节点
ret += p->ch;
p = tree; //从根节点开始重新找下一个字母
}
}
return ret;
}
void deleteTree(node *tree){ //释放空间
if(tree->lchild != NULL) deleteTree(tree->lchild);
if(tree->rchild != NULL) deleteTree(tree->rchild);
deleteTree(tree);
}
int main(){
string encodeStr = "aaaaaabbbbccddd";
node *tree = createTree(encodeStr);
printInfo(tree,"");
string decodeStr = "010110111";
string str = decode(tree,decodeStr); //解码
cout<<decodeStr<<":"<<str<<endl;
return 0;
}

1万+

被折叠的 条评论
为什么被折叠?



