时间过的真快,转眼之间一个学期即将结束,想必这个时候大家都在准备各科的课设作业,本期内容是我的数据结构课设,希望能给大家带来帮助,如果有任何不足或需要改进的地方,欢迎各位提出宝贵的意见。
屏幕录制2023-12-24 13.43.01
课设要求
哈夫曼树应用 题目描述及功能要求
- 从文件 Text.txt 中读取一大段文字(字符),统计其中不同字符出现频度(百分比),将这些字符 以及对应频度统计结果存于文件 Freq.txt 中。从 Freq.txt 文件中读取频度并按此频度创建哈夫曼树。
- 建立哈夫曼树并将它存于文件HuffTree.txt中(以顺序存储方式,结点结构(权值,双亲,左,右). 将已在内存中的哈夫曼树以直观的方式(比如树)显示在终端上;(可以以树的凹入表示法在屏幕上显示 哈夫曼树)。
- 利用已经建好的哈夫曼树(如不在内存,则从文件 HuffTree.txt 中读入),给各字符进行哈夫曼编 码,并将编码结果存于另一个文件 HuffCode.txt 中。
- 输出该哈夫曼树的 WPL 值。
- 从键盘另外输入一段字符,所出现的字符,将输入的正文内容进行哈夫曼编码,如果某字符并没 有在哈夫曼编码表中,则该字符原样不变,若存在则进行二进制编码替换,将所得编码结果也保存在文 件 HuffEncoding.txt 中,同时也显示在终端上。
- 将二进制编码的结果从文件 HuffEncoding.txt 中读出再进行解码,显示出第 5 步中输入的那段字 符。
过程
1.数据结构
因为每个字符只能是哈夫曼树的叶子结点,所以要标记一下叶子结点。
typedef struct node {
//权重
int weight;
//左右孩子,双亲
node *lchild, *rchild, *parent;
//叶子结点标志 false 叶子结点 true 非叶子结点
bool flag;
} HuffmanNode;
typedef struct tree {
//根结点
HuffmanNode *head;
//叶子结点个数
int count;
} HuffmanTree;
//叶子结点数组
HuffmanNode *CH[26];
//哈夫曼编码结果
int HuffmanCode[26];
//WPL
int W;
//每个字符的权重
int weight[26];
//权重总和
int total;
//标记元素是否已经在哈夫曼树上
int status[26];
//每个字符的哈夫曼编码
int HuffmanCodes[26][26];
//
HuffmanTree *tree = new HuffmanTree;
2.主要函数
菜单
void menu() {
cout << "-----------------------------------------------------------------------" << endl;
cout << "| |" << endl;
cout << "| 欢 迎 回 来 |" << endl;
cout << "| |" << endl;
cout << "-----------------------------------------------------------------------" << endl;
cout << endl;
while (true) {
int op;
cout << "* 1.哈夫曼树的应用" << endl << "* 2.退出" << endl;
cin >> op;
if (op == 1) Huffmantree();
else if (op == 2)bye();
else cout << "输出有误!!!" << endl;
}
}
退出函数
void bye() {
::exit(0);
}
接下来就是核心部分了
欢迎界面
void welcome() {
cout << "-----------------------------------------------------------------------" << endl;
cout << "| |" << endl;
cout << "| 哈 夫 曼 树 应 用 |" << endl;
cout << "| |" << endl;
cout << "-----------------------------------------------------------------------" << endl;
cout << endl;
};
初始化
void init(int flag){
tree->count = 0;
total = 0;
W=0;
if (flag)generateWeight(tree, flag);
memset(status, 0, sizeof status);
memset(HuffmanCodes, -1, sizeof HuffmanCodes);
}
哈夫曼树主函数
void Huffmantree() {
//初始化
init(0);
//欢迎界面
welcome();
//生成权重
generateWeight(tree, 0);
//打印权重
printWeight();
sleep(1);
//生成哈夫曼树
generate(tree);
//哈夫曼树写入文件
writeTree(tree->head);
//打印哈夫曼树
printTree(0, tree->head);
sleep(1);
//哈夫曼编码
code(tree, 0);
//重新获取权重
generateWeight(tree, 0);
//计算WPL
show();
WPL(tree->head, 0);
cout << " = " << W << endl;
//从键盘读入字符,生成哈夫曼树
//初始化
init(1);
//生成哈夫曼树
generate(tree);
//哈夫曼编码
code(tree, 1);
//输入文本
Input();
//解码
decode(tree->head);
sleep(1);
cout<<endl;
}
生成权重
因为字符可以从文件读取,也可以从键盘读取,所以提供了两种选择,flag=0是从文件读,flag=1是从键盘读
(从文件读数据)
void generateWeight(HuffmanTree *t, int flag) {
if (!flag) {
cout << "正在努力读取文件..." << endl;
sleep(1);
fstream in;
in.open("/Users/yuwei/Desktop/c++/practice/Text.txt", ios::in);
memset(weight, 0, sizeof weight);
char c;
while (c = in.get()) {
//weight=0,说明改字符第一次出现,
if (weight[c - 'a'] == 0)t->count++;
weight[c - 'a']++;
//字符总数
total++;
}
in.close();
} else {
cout << "请输入字符" << endl;
memset(weight, 0, sizeof weight);
string ch;
cin >> ch;
for (char c: ch) {
if (c) {
//weight=0,说明改字符第一次出现,
if (weight[c - 'a'] == 0)t->count++;
weight[c - 'a']++;
//字符总数
total++;
}
}
}
}
打印权重
void printWeight() {
//将权重存入文件中
fstream out;
out.open("/Users/yuwei/Desktop/c++/practice/Freq.txt", ios::out);
cout << "-----------------------------------------------------------------------" << endl;
cout << " 权 重 " << endl;
cout << "-----------------------------------------------------------------------" << endl;
//第一行:字符
for (int i = 0; i < 26; i++) {
if (weight[i] != 0) {
//在终端显示
printf("%c\t", 'a' + i);
// 写入文件
out.put('a' + i);
out.put('\t');
}
}
cout << endl;
out.put('\n');
//第二行:权重
for (int i = 0; i < 26; i++) {
if (weight[i] != 0) {
cout << weight[i] << "\t";
//权重可能大于10,不能当作一个字符,必须转成字符串
string s = to_string(weight[i]);
for (char c: s) {
out.put(c);
}
out.put('\t');
}
}
cout << endl;
out.put('\n');
//第三行:比例
for (int i = 0; i < 26; i++) {
if (weight[i] != 0) {
cout << (weight[i] * 100) / total << "%\t";
string s = to_string((weight[i] * 100) / total);
for (char c: s) {
out.put(c);
}
out.put('%');
out.put('\t');
}
}
cout << endl << endl;
out.close();
}
生成哈夫曼树
void generate(HuffmanTree *t) {
cout << "努力构建哈夫曼树ing...";
cout << endl;
//间隔1s
sleep(1);
cout << "-----------------------------------------------------------------------" << endl;
cout << " 哈 夫 曼 树 " << endl;
cout << "-----------------------------------------------------------------------" << endl;
for (int i = 0; i < 26; i++) {
//生成叶子结点
CH[i] = new HuffmanNode;
CH[i]->weight = 'a' + i;
CH[i]->flag = false;
CH[i]->lchild = CH[i]->rchild = nullptr;
//如果weight为0说明改字符未出过,所以赋值为0x3ffff,作为标记
if (!weight[i])weight[i] = 0x3ffff;
}
//f:未选结点中最小的权值最小的结点id,s:未选结点中最小的权值第二小的结点id
int f, s;
//进行t-》count-1次就能构造一颗哈夫曼树,比如只有两个字符,只须一步就能构造哈夫曼树
for (int i = 1; i < t->count; i++) {
//find :查找未选结点中最小的权值最小的结点id
f = find();
//加入哈夫曼树,更新status
status[f] = 1;
s = find();
//用第weight[s]来储存新生成的结点
weight[s] = weight[f] + weight[s];
HuffmanNode *tem = new HuffmanNode;
//更新根结点
t->head = tem;
//更新左右孩子
tem->lchild = CH[f];
tem->rchild = CH[s];
//更新双亲
CH[f]->parent = CH[s]->parent = tem;
tem->weight = weight[s];
//非叶子结点
tem->flag = true;
//将新结点加入CH中
CH[s] = tem;
}
}
find()
查找未选结点中最小的权值最小的结点id
int find() {
int min = -1;
//找到第一个未加入哈夫曼树结点的id
while (status[++min]);
for (int i = 0; i < 26; i++) {
if (!status[i]) {
if (weight[i] < weight[min])min = i;
}
}
return min;
}
哈夫曼树写入文件
n代表null
如果是叶子结点,则会在后面加上对应的字符
void writeTree(HuffmanNode *n) {
if (n == nullptr) return;
fstream out;
out.open("/Users/yuwei/Desktop/c++/practice/HuffTree.txt", ios::app);
out.write("parent: ", 8);
//权重可能大于10,不能当作一个字符,必须转成字符串
if (n->parent) {
string s = to_string(n->parent->weight);
for (char c: s) {
out.put(c);
}
out.put('\t');
} else {
out.write("n", 1);
out.put('\t');
}
out.write("weight: ", 8);
//非叶子结点
if (n->flag) {
string s = to_string(n->weight);
for (char c: s) {
out.put(c);
}
out.put('\t');
} else {
string s = to_string(weight[n->weight - 'a']);
for (char c: s) {
out.put(c);
}
out.put('\t');
}
//左右孩子
out.write("lchild: ", 8);
//非叶子结点
if (n->lchild) {
//左孩子非叶子结点
if (n->lchild->flag) {
string s = to_string(n->lchild->weight);
for (char c: s) {
out.put(c);
}
out.put('\t');
} else {
string s = to_string(weight[n->lchild->weight - 'a']);
for (char c: s) {
out.put(c);
}
out.put('\t');
}
} else {
out.write("n", 1);
out.put('\t');
}
//右孩子
out.write("rchild: ", 4);
//非叶子结点
if (n->rchild) {
//左孩子非叶子结点
if (n->rchild->flag) {
string s = to_string(n->rchild->weight);
for (char c: s) {
out.put(c);
}
out.put('\t');
} else {
string s = to_string(weight[n->rchild->weight - 'a']);
for (char c: s) {
out.put(c);
}
out.put('\t');
}
} else {
out.write("n", 1);
out.put('\t');
}
if (!n->flag) {
//如果是叶子结点
out.write("char: ", 6);
out.put(n->weight);
}
out.put('\n');
out.close();
writeTree(n->lchild);
writeTree(n->rchild);
}
打印哈夫曼树
采用以树的凹入表示法在屏幕上显示 哈夫曼树
void printTree(int num, HuffmanNode *head) {
if (head == nullptr)return;
//按照中序顺序便利
printTree(num + 1, head->lchild);
//树的凹入表示法在屏幕上显示 哈夫曼树
for (int i = 0; i < 15 - 3 * num; i++)cout << " ";
if (head->flag)cout << head->weight;
else printf("%c", head->weight);
for (int i = 0; i <= 3 * num; i++) {
cout << "--";
}
cout << endl;
printTree(num + 1, head->rchild);
}
哈夫曼编码
void code(HuffmanTree *t, int flag) {
cout << "哈夫曼树编码中ing...";
cout << endl;
sleep(1);
if (!flag)
//将结果写进文件
write(0, 0, t->head);
else
print(0, 0, t->head);
cout << "-----------------------------------------------------------------------" << endl;
cout << " 编 码 完 成 " << endl;
cout << "-----------------------------------------------------------------------" << endl;
}
void write(int i, int v, HuffmanNode *t) {
if (t == nullptr)return;
HuffmanCode[i] = v;
write(i + 1, 0, t->lchild);
//如果是叶子结点则写入文件中
if (!t->flag) {
fstream out;
out.open("/Users/yuwei/Desktop/c++/practice/HuffCode.txt", ios::app);
out.put(t->weight);
out.put(':');
for (int j = 1; j <= i; j++)
//数字转字符
out.put(HuffmanCode[j] + '0');
out.put('\n');
out.close();
}
write(i + 1, 1, t->rchild);
}
计算WPL
void WPL(HuffmanNode *n, int i) {
if (n == nullptr)return;
WPL(n->lchild, i + 1);
if (!n->flag) {
W += i * weight[n->weight - 'a'];
cout << i << " * " << weight[n->weight - 'a'] << " + ";
}
WPL(n->rchild, i + 1);
}
从键盘读入字符构造哈夫曼编码
//哈夫曼编码
code(tree, 1);
输入文本进行编码
void Input() {
cout << "请输入文本" << endl;
string ch;
cin >> ch;
fstream out;
out.open("/Users/yuwei/Desktop/c++/practice/HuffEncoding.txt", ios::out);
for (char c: ch) {
if (c) {
//不等于-1说明该字符的编码存在
if (HuffmanCodes[c - 'a'][0] != -1) {
for (int j = 0; HuffmanCodes[c - 'a'][j] != -1; j++) {
out.put(HuffmanCodes[c - 'a'][j] + '0');
cout << HuffmanCodes[c - 'a'][j];
}
} else {
cout << c;
out.put(c);
}
}
}
out.close();
cout << "编码完成!!!";
cout << endl;
sleep(1);
}
解码
void decode(HuffmanNode *head) {
cout << "努力解码中ing" << endl;
sleep(1);
fstream in;
in.open("/Users/yuwei/Desktop/c++/practice/HuffEncoding.txt", ios::in);
char c;
HuffmanNode *tem = new HuffmanNode ;
tem = head;
c=in.get();
while ((c>'a'&&c<'z')||c=='0'||c=='1'){
if (c == '0') {
if(tem){
tem = tem->lchild;
findChar(&tem);
}
} else if (c == '1') {
if(tem){
tem = tem->rchild;
findChar(&tem);
}
} else cout << c;
c=in.get();
}
in.close();
}
void findChar(HuffmanNode **n) {
if ((*n)->flag)return;
//叶子结点直接输出结果
else {
printf("%c", (*n)->weight);
//找到字符后,再从头开始
(*n) = tree->head;
}
}
完整代码
#include <iostream>
#include <unistd.h>
#include <cstdio>
#include <fstream>
#include <string>
using namespace std;
typedef struct node {
//权重
int weight;
//左右孩子,双亲
node *lchild, *rchild, *parent;
//叶子结点标志 false 叶子结点 true 非叶子结点
bool flag;
} HuffmanNode;
typedef struct tree {
//根结点
HuffmanNode *head;
//叶子结点个数
int count;
} HuffmanTree;
//叶子结点数组
HuffmanNode *CH[26];
//哈夫曼编码结果
int HuffmanCode[26];
//WPL
int W;
//每个字符的权重
int weight[26];
//权重总和
int total;
//标记元素是否已经在哈夫曼树上
int status[26];
//每个字符的哈夫曼编码
int HuffmanCodes[26][26];
//
HuffmanTree *tree = new HuffmanTree;
// 欢迎界面
void welcome();
//生成权重,flag:0:从文件读取字符,1:从键盘读入
void generateWeight(HuffmanTree *t, int flag);
//打印哈夫曼树, num是层数
void printTree(int num, HuffmanNode *head);
//将哈夫曼树写入文件
void writeTree(HuffmanNode *n);
//计算WPL显示界面
void show();
void WPL(node *head, int i);
//哈夫曼树核心函数
void Huffmantree();
void bye();
//flag:0 编码结果写入文件,flag:1编码结果存入数组
void code(HuffmanTree *t, int flag);
//打印权重
void printWeight();
//查找未选结点中最小的权值最小的结点id
int find();
//将编码结果写入文件 , num :层数 v:编码值
void write(int num, int v, HuffmanNode *n);
//将编码结果写入二维数组 , num :层数 v:编码值
void print(int i, int v, HuffmanNode *t);
//从键盘输入内容,并将结果存入文件中
void Input();
//生成哈夫曼树
void generate(HuffmanTree *t);
//解码
void decode(HuffmanNode *head);
//根据哈夫曼编码找字符
void findChar(HuffmanNode **n);
//初始化
void init(int flag);
void menu() {
cout << "-----------------------------------------------------------------------" << endl;
cout << "| |" << endl;
cout << "| 欢 迎 回 来 |" << endl;
cout << "| |" << endl;
cout << "-----------------------------------------------------------------------" << endl;
cout << endl;
while (true) {
int op;
cout << "* 1.哈夫曼树的应用" << endl << "* 2.退出" << endl;
cin >> op;
if (op == 1) Huffmantree();
else if (op == 2)bye();
else cout << "输出有误!!!" << endl;
}
}
void welcome() {
cout << "-----------------------------------------------------------------------" << endl;
cout << "| |" << endl;
cout << "| 哈 夫 曼 树 应 用 |" << endl;
cout << "| |" << endl;
cout << "-----------------------------------------------------------------------" << endl;
cout << endl;
};
void init(int flag){
tree->count = 0;
total = 0;
W=0;
if (flag)generateWeight(tree, flag);
memset(status, 0, sizeof status);
memset(HuffmanCodes, -1, sizeof HuffmanCodes);
}
void Huffmantree() {
//初始化
init(0);
//欢迎界面
welcome();
//生成权重
generateWeight(tree, 0);
//打印权重
printWeight();
sleep(1);
//生成哈夫曼树
generate(tree);
//哈夫曼树写入文件
writeTree(tree->head);
//打印哈夫曼树
printTree(0, tree->head);
sleep(1);
//哈夫曼编码
code(tree, 0);
//重新获取权重
generateWeight(tree, 0);
//计算WPL
show();
WPL(tree->head, 0);
cout << " = " << W << endl;
//从键盘读入字符,生成哈夫曼树
//初始化
init(1);
//生成哈夫曼树
generate(tree);
//哈夫曼编码
code(tree, 1);
//输入文本
Input();
//解码
decode(tree->head);
sleep(1);
cout<<endl;
}
void bye() {
::exit(0);
}
void printWeight() {
//将权重存入文件中
fstream out;
out.open("/Users/yuwei/Desktop/c++/practice/Freq.txt", ios::out);
cout << "-----------------------------------------------------------------------" << endl;
cout << " 权 重 " << endl;
cout << "-----------------------------------------------------------------------" << endl;
//第一行:字符
for (int i = 0; i < 26; i++) {
if (weight[i] != 0) {
//在终端显示
printf("%c\t", 'a' + i);
// 写入文件
out.put('a' + i);
out.put('\t');
}
}
cout << endl;
out.put('\n');
//第二行:权重
for (int i = 0; i < 26; i++) {
if (weight[i] != 0) {
cout << weight[i] << "\t";
//权重可能大于10,不能当作一个字符,必须转成字符串
string s = to_string(weight[i]);
for (char c: s) {
out.put(c);
}
out.put('\t');
}
}
cout << endl;
out.put('\n');
//第三行:比例
for (int i = 0; i < 26; i++) {
if (weight[i] != 0) {
cout << (weight[i] * 100) / total << "%\t";
string s = to_string((weight[i] * 100) / total);
for (char c: s) {
out.put(c);
}
out.put('%');
out.put('\t');
}
}
cout << endl << endl;
out.close();
}
void generate(HuffmanTree *t) {
cout << "努力构建哈夫曼树ing...";
cout << endl;
//间隔1s
sleep(1);
cout << "-----------------------------------------------------------------------" << endl;
cout << " 哈 夫 曼 树 " << endl;
cout << "-----------------------------------------------------------------------" << endl;
for (int i = 0; i < 26; i++) {
//生成叶子结点
CH[i] = new HuffmanNode;
CH[i]->weight = 'a' + i;
CH[i]->flag = false;
CH[i]->lchild = CH[i]->rchild = nullptr;
//如果weight为0说明改字符未出过,所以赋值为0x3ffff,作为标记
if (!weight[i])weight[i] = 0x3ffff;
}
//f:未选结点中最小的权值最小的结点id,s:未选结点中最小的权值第二小的结点id
int f, s;
//进行t-》count-1次就能构造一颗哈夫曼树,比如只有两个字符,只须一步就能构造哈夫曼树
for (int i = 1; i < t->count; i++) {
//find :查找未选结点中最小的权值最小的结点id
f = find();
//加入哈夫曼树,更新status
status[f] = 1;
s = find();
//用第weight[s]来储存新生成的结点
weight[s] = weight[f] + weight[s];
HuffmanNode *tem = new HuffmanNode;
//更新根结点
t->head = tem;
//更新左右孩子
tem->lchild = CH[f];
tem->rchild = CH[s];
//更新双亲
CH[f]->parent = CH[s]->parent = tem;
tem->weight = weight[s];
//非叶子结点
tem->flag = true;
//将新结点加入CH中
CH[s] = tem;
}
}
void printTree(int num, HuffmanNode *head) {
if (head == nullptr)return;
//按照中序顺序便利
printTree(num + 1, head->lchild);
//树的凹入表示法在屏幕上显示 哈夫曼树
for (int i = 0; i < 15 - 3 * num; i++)cout << " ";
if (head->flag)cout << head->weight;
else printf("%c", head->weight);
for (int i = 0; i <= 3 * num; i++) {
cout << "--";
}
cout << endl;
printTree(num + 1, head->rchild);
}
int find() {
int min = -1;
//找到第一个未加入哈夫曼树结点的id
while (status[++min]);
for (int i = 0; i < 26; i++) {
if (!status[i]) {
if (weight[i] < weight[min])min = i;
}
}
return min;
}
void code(HuffmanTree *t, int flag) {
cout << "哈夫曼树编码中ing...";
cout << endl;
sleep(1);
if (!flag)
//将结果写进文件
write(0, 0, t->head);
else
print(0, 0, t->head);
cout << "-----------------------------------------------------------------------" << endl;
cout << " 编 码 完 成 " << endl;
cout << "-----------------------------------------------------------------------" << endl;
}
void write(int i, int v, HuffmanNode *t) {
if (t == nullptr)return;
HuffmanCode[i] = v;
write(i + 1, 0, t->lchild);
//如果是叶子结点则写入文件中
if (!t->flag) {
fstream out;
out.open("/Users/yuwei/Desktop/c++/practice/HuffCode.txt", ios::app);
out.put(t->weight);
out.put(':');
for (int j = 1; j <= i; j++)
//数字转字符
out.put(HuffmanCode[j] + '0');
out.put('\n');
out.close();
}
write(i + 1, 1, t->rchild);
}
void writeTree(HuffmanNode *n) {
if (n == nullptr) return;
fstream out;
out.open("/Users/yuwei/Desktop/c++/practice/HuffTree.txt", ios::app);
out.write("parent: ", 8);
//权重可能大于10,不能当作一个字符,必须转成字符串
if (n->parent) {
string s = to_string(n->parent->weight);
for (char c: s) {
out.put(c);
}
out.put('\t');
} else {
out.write("n", 1);
out.put('\t');
}
out.write("weight: ", 8);
//非叶子结点
if (n->flag) {
string s = to_string(n->weight);
for (char c: s) {
out.put(c);
}
out.put('\t');
} else {
string s = to_string(weight[n->weight - 'a']);
for (char c: s) {
out.put(c);
}
out.put('\t');
}
//左右孩子
out.write("lchild: ", 8);
//非叶子结点
if (n->lchild) {
//左孩子非叶子结点
if (n->lchild->flag) {
string s = to_string(n->lchild->weight);
for (char c: s) {
out.put(c);
}
out.put('\t');
} else {
string s = to_string(weight[n->lchild->weight - 'a']);
for (char c: s) {
out.put(c);
}
out.put('\t');
}
} else {
out.write("n", 1);
out.put('\t');
}
//右孩子
out.write("rchild: ", 4);
//非叶子结点
if (n->rchild) {
//左孩子非叶子结点
if (n->rchild->flag) {
string s = to_string(n->rchild->weight);
for (char c: s) {
out.put(c);
}
out.put('\t');
} else {
string s = to_string(weight[n->rchild->weight - 'a']);
for (char c: s) {
out.put(c);
}
out.put('\t');
}
} else {
out.write("n", 1);
out.put('\t');
}
if (!n->flag) {
//如果是叶子结点
out.write("char: ", 6);
out.put(n->weight);
}
out.put('\n');
out.close();
writeTree(n->lchild);
writeTree(n->rchild);
}
//
void print(int i, int v, HuffmanNode *t) {
if (t == nullptr)return;
HuffmanCode[i] = v;
print(i + 1, 0, t->lchild);
//如果是叶子结点则写入文件中
if (!t->flag) {
for (int j = 1; j <= i; j++) {
//数字转字符
HuffmanCodes[t->weight - 'a'][j - 1] = HuffmanCode[j];
}
}
print(i + 1, 1, t->rchild);
}
void Input() {
cout << "请输入文本" << endl;
string ch;
cin >> ch;
fstream out;
out.open("/Users/yuwei/Desktop/c++/practice/HuffEncoding.txt", ios::out);
for (char c: ch) {
if (c) {
//不等于-1说明该字符的编码存在1
if (HuffmanCodes[c - 'a'][0] != -1) {
for (int j = 0; HuffmanCodes[c - 'a'][j] != -1; j++) {
out.put(HuffmanCodes[c - 'a'][j] + '0');
cout << HuffmanCodes[c - 'a'][j];
}
} else {
cout << c;
out.put(c);
}
}
}
out.close();
cout << "编码完成!!!";
cout << endl;
sleep(1);
}
void WPL(HuffmanNode *n, int i) {
if (n == nullptr)return;
WPL(n->lchild, i + 1);
if (!n->flag) {
W += i * weight[n->weight - 'a'];
cout << i << " * " << weight[n->weight - 'a'] << " + ";
}
WPL(n->rchild, i + 1);
}
void show() {
cout << "努力计算WPLing...";
cout << endl;
sleep(1);
cout << "-----------------------------------------------------------------------" << endl;
cout << " W P L " << endl;
cout << "-----------------------------------------------------------------------" << endl;
cout << "WPL: ";
}
void generateWeight(HuffmanTree *t, int flag) {
if (!flag) {
cout << "正在努力读取文件..." << endl;
sleep(1);
fstream in;
in.open("/Users/yuwei/Desktop/c++/practice/Text.txt", ios::in);
memset(weight, 0, sizeof weight);
char c;
while (c = in.get()) {
//weight=0,说明改字符第一次出现,
if (weight[c - 'a'] == 0)t->count++;
weight[c - 'a']++;
//字符总数
total++;
}
in.close();
} else {
cout << "请输入字符" << endl;
memset(weight, 0, sizeof weight);
string ch;
cin >> ch;
for (char c: ch) {
if (c) {
//weight=0,说明改字符第一次出现,
if (weight[c - 'a'] == 0)t->count++;
weight[c - 'a']++;
//字符总数
total++;
}
}
}
}
void decode(HuffmanNode *head) {
cout << "努力解码中ing" << endl;
sleep(1);
fstream in;
in.open("/Users/yuwei/Desktop/c++/practice/HuffEncoding.txt", ios::in);
char c;
HuffmanNode *tem = new HuffmanNode ;
tem = head;
c=in.get();
while ((c>'a'&&c<'z')||c=='0'||c=='1'){
if (c == '0') {
if(tem){
tem = tem->lchild;
findChar(&tem);
}
} else if (c == '1') {
if(tem){
tem = tem->rchild;
findChar(&tem);
}
} else cout << c;
c=in.get();
}
in.close();
}
void findChar(HuffmanNode **n) {
if ((*n)->flag)return;
//叶子结点直接输出结果
else {
printf("%c", (*n)->weight);
//找到字符后,再从头开始
(*n) = tree->head;
}
}
int main() {
menu();
}
小结
本课设用到的知识
树的创建和遍历
哈夫曼树的构建和应用
c++文件的读写
再次感谢你的阅读,希望本文对你有所帮助。