数据结构实验2
题目要求
实现一个哈夫曼编码系统,系统包括以下功能:
(1) 字符信息统计:读取待编码的源文件SourceFile.txt,统计出现的字符及其频率。
(2) 建立哈夫曼树:根据统计结果建立哈夫曼树以及哈夫曼码表,将各字符对应的编码表保存在文件Code.txt中。
(3) 对源文件进行编码:根据哈夫曼码表,将SourceFile.txt中的字符转换成相应的编码文件ResultFile.txt。
(4) 选做内容:
完成译码功能:对任意一个给定的由01组成的文件,根据哈夫曼码表翻译成由字符组成的源文件。
分析
这是一个即实用又有趣的题目,但是设计到很多的知识点,非常耗时。若用c++实现最好有c++ STL 使用基础。
我将程序分成几个主要部分:
- 统计文章的字符出现频率。
- 构造哈夫曼树并生成哈夫曼编码。
- 将文章按照生成的哈弗曼编码加密成只含有0和1的问。
- 保存编码到文件,读取编码并还原哈夫曼树。
- 读取经过特定编码加密的文件,并又这个编码树还原成可读的内容。
简单实现哈夫曼方法请看:我的哈夫曼算法
知识点
【文件读写 】
如读取原文,保存编码, 难点是将数据序列化和反序列化。
【c++ map】
用来保存各个字符出现的次数,若不会使用,将难以下手或代码量倍增。
【c++ primary_queue】
用于构造哈夫曼树,能极大提高效率和缩短代码长度
笔记
第一次写时用char来保存字符,但是后来发现原文中若出现中文,char类型没法保存,最后溢出了。于是用整数来保存
字符,输出时简单的类型转换即可。
? 以下代码实现题目基本要求和选做内容
MYCODE
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<string>
#include<algorithm>
#include<fstream>
#include<queue>
#include<map>
using namespace std;
const char *sourcefile = "D://SourceFile.txt"; //原文
const char *mapfile = "D://mapfile.txt"; //存储字典的文件
const char *encryptfile = "D://entryfile.txt"; //存储原文加密后形成的文本
ofstream mapf;
map<int , int> iimap; //保存字符在原文中出现的字典,用int来保存字符
map<int , string> ccmap; //保存字符对应hufuman编码的字典
//哈夫曼树节点结构
struct node{
int val; //字符
int times; //出现次数
string code; //哈夫曼编码
node* left;
node* right;
node(int c, int t, node* l, node* r){
val = c;
times = t;
right = r;
left = l;
}
bool operator < (const node &n){
return this->times > n.times;
}
};
struct cmp{
bool operator()(const node* a, const node* b){
return a->times > b->times;
}
};
//保存节点的优先队列,times小的节点优先输出
priority_queue<node*, vector<node*>, cmp> pq;
//读取原文并且统计每个字符出现的次数
void Read_and_static(){
ifstream fout;
string buf;
fout.open(sourcefile