1、主要数据类型与变量
1.1使用到的头文件
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map> //map数据结构存储HT编码表
#include <queue> //构建的节点的优先性
#include <string> //字符串方便输入输出
#include <iterator> //迭代器输出map展示
#include <fstream> //读写文件
1.2 使用类代替结构体,这里重载比较运算符,便于排序和构造优先队列。
class HTNode{
public:
char ch; //字符
int weight;//权重
HTNode *left;//左孩子
HTNode *right;//右孩子
HTNode(int weight) : weight(weight) {
}
//重载比较运算符,便于排序,构造优先队列
bool operator<(const HTNode &htnode) const{
return weight > htnode.weight;
}
//两个构造函数
HTNode(char ch, int weight, HTNode *left, HTNode *right) : ch(ch), weight(weight), left(left), right(right) {
}
HTNode(char ch, int weight) : ch(ch), weight(weight) {
}
};
1.3函数结构说明
/**
* 通过优先队列构建赫夫曼树
* @param queue
*/
void CreateHuffmanTree(priority_queue<HTNode> &queue);
/**
* 通过字符串统计字符的频率
* @param s 需要统计的源数据
* @return 返回一个优先队列,方便赫夫曼树筛选最小节点
*/
priority_queue<HTNode> count(string s);
/**
* 展示每个字符对应的权重
* @param q 优先字符队列
*/
void show(priority_queue<HTNode> q);
/**
* 通过路径读取文件
* @param path 需要读的文件路径
* @return //以字符串类型返回文件中的数据
*/
string readFile(string path);
/**
* 根据路径写入文件
* @param path 文件路径
* @param data 需要写入文件的内容(字符串类型)
*/
void writeFile(string path,string data);
void writeFile(string path,char data);//重载写文件函数,以char类型写入
static map<char,string> huffmanCode; //静态的全局变量map集合:key为字符,string为对应编码,用来作为编码表
/**
* 获取编码表,此处配合静态的Map集合存入编码
* @param root 赫夫曼树的根节点
* @param code 路径编码,右为1,左为0
* @param prefix 到该节点的路径,因为使用递归,所以要传入地址
*/
void getCodes(HTNode *root,string code,string &prefix);
/**
* 打印编码表
* @param codes 通过map集合配合迭代器输出每个字符对应的编码
*/
void printCode(map<char,string> codes);
/**
* 通过编码表和文件读取出的数据来生成->编码数据
* @param codetTable 编码表
* @param data 数据源
* @return 返回字符串展示编码数据
*/
string BecomeCode(map<char,string> codetTable,string data);
/**
* 解码:通过编码表和编码后的数据
* @param codetTable 编码表
* @param CodeData 编码数据
*/
void deCode(map<char,string> codetTable,string CodeData);
2、算法或程序模块
2.1 程序流程解释:
①创建赫夫曼树:统计字符的频率由小到大放入优先队列,通过队列找出最小频率构建赫夫曼树。
②生成赫夫曼编码和赫夫曼编码后的数据:通过递归遍历赫夫曼树,通过Map集合创建编码表,再使用编码表和源数据生成编码后的数据。
③使用赫夫曼编码解码:通过查找编码后的数据配合编码表,通过查找方式输出对应的字符
核心函数解释
构造赫夫曼树:最小左右孩子的权重相加,生成父节点,然后父节点进队列
/**
* 创建赫夫曼树
* @param queue 构造的节点队列
* @return 返回哈夫曼树的根节点
*/
void CreateHuffmanTree(priority_queue<HTNode> &queue){
while (queue.size()>1){
HTNode *left = new HTNode(queue.top()); queue.pop(); //队列弹出左右孩子
HTNode *right = new HTNode(queue.top()); queue.pop();
HTNode parent('R',left->weight + right->weight,left,right);//通过最小的两个节点权重相加构造父节点
queue.push(parent);//父节点进队列
}
}
统计每个字符出现的频率:字符范围是ASCALL:0-128
priority_queue<HTNode> count(string s){
int a[128