我是靠谱客的博主 个性高山,这篇文章主要介绍数据结构实验三:Huffman树及Huffman编码的算法实现Exp03 Huffman树及Huffman编码的算法实现,现在分享给大家,希望可以做个参考。

Exp03 Huffman树及Huffman编码的算法实现

Author: Maskros

实验目的

  • 了解该树的应用实例,熟悉掌握Huffman树的构造方法及Huffman编码的应用,

  • 了解Huffman树在通信、编码领域的应用过程。Huffman树及Huffman编码的算法实现

实验内容与要求

  1. 输入一段100—200字的英文短文,存入一文件a中。

  2. 写函数统计短文出现的字母个数n及每个字母的出现次数

  3. 写函数以字母出现次数作权值,建Haffman树(n个叶子),给出每个字母的Haffman编码。

  4. 用每个字母编码对原短文进行编码,码文存入文件b中。

  5. 用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
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
//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; }

实验用测试数据和相关结果分析

复制代码
1
2
3
4
5
6
7
8
9
10
11
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内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(61)

评论列表共有 0 条评论

立即
投稿
返回
顶部