我是靠谱客的博主 个性高山,最近开发中收集的这篇文章主要介绍数据结构实验三:Huffman树及Huffman编码的算法实现Exp03 Huffman树及Huffman编码的算法实现,觉得挺不错的,现在分享给大家,希望可以做个参考。
概述
Exp03 Huffman树及Huffman编码的算法实现
Author: Maskros
实验目的
-
了解该树的应用实例,熟悉掌握Huffman树的构造方法及Huffman编码的应用,
-
了解Huffman树在通信、编码领域的应用过程。Huffman树及Huffman编码的算法实现
实验内容与要求
-
输入一段100—200字的英文短文,存入一文件a中。
-
写函数统计短文出现的字母个数n及每个字母的出现次数
-
写函数以字母出现次数作权值,建Haffman树(n个叶子),给出每个字母的Haffman编码。
-
用每个字母编码对原短文进行编码,码文存入文件b中。
-
用Haffman树对b中码文进行译码,结果存入文件c中,比较a,c是否一致,以检验编码、译码的正确性。
实验内容和实验步骤
通过优先队列 priority_queue和 map简化建树和编码过程
- 大体思路:
- 需要进行文件读写操作,通过
fopen()
,fputc()
,fputs()
,fclose()
等函数实现 - 定义结点
struct Node
, 其中存储char alpha
作为字母,int value
对应字母的权值,Node *lchild,*rchild
对应左右孩子结点,string code
存储编码后的Huffman编码,构造函数不再赘述。 write_file(char *name)
函数,为了读入回车字符,使用*
作为读入结束标志,同时存入数组和文件中cal_alpha(vector<char> v,int l)
函数运用map<char,int>
进行映射,键为字母,值为出现的次数,使用print_times()
函数进行打印create_HT()
函数用于建立Huffman树,首先将map<char,int>
压入优先队列priority_queue<Node*,vector<Node*>,cmp>
中,其中bool cmp(Node *a,Node *b)
定义按照字母的权重从小到大排序,这样每次取出队首两个结点构成新节点压入队列,循环往复直到队空,将最后两个结点结合作为Huffman树的根节点encode_HT(Node *p, string ss)
函数用于编码Huffman树,从根节点前序遍历整棵树,左子树在字符串后加0
, 右子树加1
, 递归遍历即可,print_hfcode()
用于打印哈夫曼编码decode_Text(char *name)
函数用于对文件中的密文解码,从根结点遍历整棵树,检测到0
就往左孩子找,1
就去右孩子找,如果对应结点的alpha
值为字母即将其添加到译文中,然后在返回根节点遍历,以此往复,最后将结果译文写入文件中- tips:程序对只有一个结点的Huffman树进行了特判
- 需要进行文件读写操作,通过
- 输入形式:一段英文短文可包含逗号等标点以及回车,空格等白字符。输入以
*
符号结束 - 输出形式:包含字母数量、各字母的出现次数、每个字母对应的哈夫曼编码。原文、编码后的密文、以及解码后的密文分别保存在源目录的
a.txt
,b.txt
,c.txt
中
//presented by Maskros - 2021/05/20
#include<bits/stdc++.h>
using namespace std;
vector<char> s; //Save the original text
string s2=""; //Save the original text after encoding
map<char,int> mp; //Count the number of occurrences of letters
map<char,string> hfcode; //Save Huffman Code
int len,len2; //Text length
map<char,int>::iterator it;
map<char,string>::iterator it2;
struct Node{
int value;
char alpha;
Node *lchild,*rchild;
string code;
Node(){}
Node(int v,char a,Node *l,Node *r):value(v),alpha(a),lchild(l),rchild(r){code="";}
};
Node *HTroot;
void write_file(char *name){ //Write file
cout<<"Print '*' to stop typing...."<<endl<<endl;
char ch;
if(FILE *fp=fopen(name,"w")){
while(1){
ch=getchar();
if(ch=='*') break; //while read '*' then end input
fputc(ch,fp);
s.push_back(ch);
}
fclose(fp);
}
}
void cal_alpha(vector<char> v,int l){ //Count the number of words appearing in a letter
for(int i=0;i<l;i++){
if((v[i]<='Z'&&v[i]>='A')||(v[i]<='z'&&v[i]>='a'))
mp[v[i]]++;
}
}
void print_times(){ //Print the number of occurrences and the number of each letter
it=mp.begin();
putchar('n');
cout<<"n="<<mp.size()<<endl;
while(it!=mp.end()){
cout<<it->first<<": "<<it->second<<endl;
it++;
}
putchar('n');
}
struct cmp{ //Used for priority queue sorting
bool operator()(Node *a,Node *b){
return a->value>b->value;
}
};
void create_HT(){ //Build Huffman Tree
priority_queue<Node*,vector<Node*>,cmp> q;
for(it=mp.begin();it!=mp.end();it++){
q.push(new Node(it->second,it->first,NULL,NULL));
}
if(mp.size()==1){HTroot=q.top(); return;} //Huffman tree has only one root node
Node *left,*right;
while(1){
left=q.top(); q.pop();
right=q.top(); q.pop();
if(q.empty()){
HTroot=new Node(left->value+right->value,'0',left,right);
break;
}
q.push(new Node(left->value+right->value,'0',left,right));
}
}
void encode_HT(Node *p,string ss){ //Coding the Huffman tree
if(!p) return;
p->code=ss;
if(p->alpha!='0'){
if(p->code.length()==0){ hfcode[p->alpha]="1"; return;} //If the Huffman tree has only one root node, the default is 1
hfcode[p->alpha]=p->code;
}
encode_HT(p->lchild,ss+"0");
encode_HT(p->rchild,ss+"1");
}
void print_hfcode(){ //Print Huffman code
for(it2=hfcode.begin();it2!=hfcode.end();it2++){
cout<<it2->first<<" => "<<it2->second<<endl;
}
}
void encode_Text(char *name){ //Write the encoded original text to the file
char tmp[100];
string st;
if(FILE *fp=fopen(name,"w")){
for(int i=0;i<len;i++){
st=hfcode[s[i]];
s2+=st;
strcpy(tmp,st.c_str()); //String to char array
fputs(tmp,fp);
}
fclose(fp);
}
}
void decode_Text(char *name){ //Decode b.txt and save in c.txt
Node *tmp=HTroot;
char decode[10000];
int j=0;
if(mp.size()==1){ //If the Huffman tree has only one root node
for(int i=0;i<s2.length();i++){
if(tmp->alpha!='0') decode[j++]=tmp->alpha;
}
}
else{
for(int i=0;i<=s2.length();i++){
if(tmp->alpha!='0'){
decode[j++]=tmp->alpha;
tmp=HTroot;
}
if(s2[i]=='0') tmp=tmp->lchild;
else tmp=tmp->rchild;
}
}
if(FILE *fp=fopen(name,"w")){
for(int i=0;i<j;i++) fputc(decode[i],fp);
fclose(fp);
}
}
int main(){
char a[]="a.txt";
char b[]="b.txt";
char c[]="c.txt";
write_file(a);
len=s.size();
cal_alpha(s,len);
print_times();
create_HT();
encode_HT(HTroot,"");
print_hfcode();
encode_Text(b);
decode_Text(c);
return 0;
}
实验用测试数据和相关结果分析
Test 1
The quick brown fox
jumps
over the lazy dog.
Test 2
aaaaa
Test 3
bbcbaaaad
- 结果分析:特例普例都能通过,起飞,更长文本的不好截图,在这里不放了
实验总结
- stl 雀实太好使了xdm,当时一看Huffman的建树方式一下就想到了
priority_queue
了,用起来太爽了,map
也为编码提供了方便 - 在程序的编写过程中,Huffman编码方式确实让我感觉非常神奇
- 文件的读写操作都忘了,现查的资料,正好复习一下TuT
最后
以上就是个性高山为你收集整理的数据结构实验三:Huffman树及Huffman编码的算法实现Exp03 Huffman树及Huffman编码的算法实现的全部内容,希望文章能够帮你解决数据结构实验三:Huffman树及Huffman编码的算法实现Exp03 Huffman树及Huffman编码的算法实现所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复