【c++、数据结构课设】哈夫曼树

时间过的真快,转眼之间一个学期即将结束,想必这个时候大家都在准备各科的课设作业,本期内容是我的数据结构课设,希望能给大家带来帮助,如果有任何不足或需要改进的地方,欢迎各位提出宝贵的意见。

屏幕录制2023-12-24 13.43.01

课设要求

哈夫曼树应用 题目描述及功能要求

  1. 从文件 Text.txt 中读取一大段文字(字符),统计其中不同字符出现频度(百分比),将这些字符 以及对应频度统计结果存于文件 Freq.txt 中。从 Freq.txt 文件中读取频度并按此频度创建哈夫曼树。
  2. 建立哈夫曼树并将它存于文件HuffTree.txt中(以顺序存储方式,结点结构(权值,双亲,左,右). 将已在内存中的哈夫曼树以直观的方式(比如树)显示在终端上;(可以以树的凹入表示法在屏幕上显示 哈夫曼树)。
  3. 利用已经建好的哈夫曼树(如不在内存,则从文件 HuffTree.txt 中读入),给各字符进行哈夫曼编 码,并将编码结果存于另一个文件 HuffCode.txt 中。
  4. 输出该哈夫曼树的 WPL 值。
  5. 从键盘另外输入一段字符,所出现的字符,将输入的正文内容进行哈夫曼编码,如果某字符并没 有在哈夫曼编码表中,则该字符原样不变,若存在则进行二进制编码替换,将所得编码结果也保存在文 件 HuffEncoding.txt 中,同时也显示在终端上。
  6. 将二进制编码的结果从文件 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);//计算WPLshow();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;//间隔1ssleep(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:未选结点中最小的权值第二小的结点idint f, s;//进行t-》count-1次就能构造一颗哈夫曼树,比如只有两个字符,只须一步就能构造哈夫曼树for (int i = 1; i < t->count; i++) {//find :查找未选结点中最小的权值最小的结点idf = find();//加入哈夫曼树,更新statusstatus[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;//找到第一个未加入哈夫曼树结点的idwhile (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);elseprint(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);//计算WPLshow();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;//间隔1ssleep(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:未选结点中最小的权值第二小的结点idint f, s;//进行t-》count-1次就能构造一颗哈夫曼树,比如只有两个字符,只须一步就能构造哈夫曼树for (int i = 1; i < t->count; i++) {//find :查找未选结点中最小的权值最小的结点idf = find();//加入哈夫曼树,更新statusstatus[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;//找到第一个未加入哈夫曼树结点的idwhile (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);elseprint(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说明该字符的编码存在1if (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++文件的读写
在这里插入图片描述

再次感谢你的阅读,希望本文对你有所帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/223981.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

bean生命周期源码(三)

书接上文 文章目录 一、Bean的销毁逻辑1. 简介2. Bean销毁逻辑的注册3. Bean的销毁过程 一、Bean的销毁逻辑 1. 简介 前面我们已经分析完了Spring创建Bean的整个过程的源码&#xff0c;在创建bean的核心方法中doCreateBean这一个核心方法中&#xff0c;在方法的最后面有这么…

pycharm修改项目文件夹名称

目录 1 修改项目文件夹名称 2 修改代码中的项目名称 1 修改项目文件夹名称 选中项目文件夹&#xff0c;右键&#xff0c;选择refactor-rename。 选择rename project&#xff1a; 然后输入新的项目名称。 此时进入资源管理器&#xff0c;修改项目文件夹的名字&#xff0c;完成…

spring aop实际开发中怎么用,Spring Boot整合AOP,spring boot加spring mvc一起使用aop,项目中使用aop

前言&#xff1a;本文不介绍 AOP 的基本概念、动态代理方式实现 AOP&#xff0c;以及 Spring 框架去实现 AOP。本文重点介绍 Spring Boot 项目中如何使用 AOP&#xff0c;也就是实际项目开发中如何使用 AOP 去实现相关功能。 如果有需要了解 AOP 的概念、动态代理实现 AOP 的&…

Spark集群部署与架构

在大数据时代&#xff0c;处理海量数据需要分布式计算框架。Apache Spark作为一种强大的大数据处理工具&#xff0c;可以在集群中高效运行&#xff0c;处理数十TB甚至PB级别的数据。本文将介绍如何构建和管理Spark集群&#xff0c;以满足大规模数据处理的需求。 Spark集群架构…

LLM微调(四)| 微调Llama 2实现Text-to-SQL,并使用LlamaIndex在数据库上进行推理

Llama 2是开源LLM发展的一个巨大里程碑。最大模型及其经过微调的变体位居Hugging Face Open LLM排行榜&#xff08;https://huggingface.co/spaces/HuggingFaceH4/open_llm_leaderboard&#xff09;前列。多个基准测试表明&#xff0c;就性能而言&#xff0c;它正在接近GPT-3.5…

光耦继电器

光耦继电器(光电继电器) AQW282SX 282SZ 280SX 280SZ 284SX 284SZ 212S 212SX 21 2SZ 文章目录 光耦继电器(光电继电器)前言一、光耦继电器是什么二、光耦继电器的类型三、光电耦合器的应用总结前言 光耦继电器在工业控制、通讯、医疗设备、家电及汽车电子等领域得到广泛应…

【隐私保护】Presidio简化了PII匿名化

自我介绍 做一个简单介绍&#xff0c;酒架年近48 &#xff0c;有20多年IT工作经历&#xff0c;目前在一家500强做企业架构&#xff0e;因为工作需要&#xff0c;另外也因为兴趣涉猎比较广&#xff0c;为了自己学习建立了三个博客&#xff0c;分别是【全球IT瞭望】&#xff0c;【…

YOLOv8改进 | 2023注意力篇 | MSDA多尺度空洞注意力(附多位置添加教程)

一、本文介绍 本文给大家带来的改进机制是MSDA&#xff08;多尺度空洞注意力&#xff09;发表于今年的中科院一区(算是国内计算机领域的最高期刊了)&#xff0c;其全称是"DilateFormer: Multi-Scale Dilated Transformer for Visual Recognition"。MSDA的主要思想是…

STM32F407-14.3.10-表73具有有断路功能的互补通道OCx和OCxN的输出控制位-1x111

如上表所示&#xff0c;MOE1&#xff0c;OSSR1&#xff0c;CCxE1&#xff0c;CCxNE1时&#xff0c;OCx与OCxN对应端口的输出状态取决于OCx_REF与极性选择&#xff08;CCxP&#xff0c;CCxNP&#xff09; 死区。 -------------------------------------------------------------…

记pbcms网站被攻击,很多标题被篡改(1)

记得定期打开网站看看哦! 被攻击后的网站异常表现:网页内容缺失或变更,页面布局破坏,按钮点击无效,...... 接着查看HTML、CSS、JS文件,发现嵌入了未知代码! 攻击1:index.html 或其他html模板页面的标题、关键词、描述被篡改(俗称,被挂马...),如下: 攻击2:在ht…

【PostGIS】PostgreSQL15+对应PostGIS安装教程及空间数据可视化

一、PostgreSQL15与对应PostGIS安装 PostgreSQL15安装&#xff1a;下载地址PostGIS安装&#xff1a;下载地址&#xff08;选择倒数第二个&#xff09; 1、PostgreSQL安装 下载安装包&#xff1b;开始安装&#xff0c;这里使用默认安装&#xff0c;一直next直到安装完成&…

ubuntu下docker安装,配置python运行环境

参考自: 1.最详细ubuntu安装docker教程 2.使用docker搭建python环境 首先假设已经安装了docker&#xff0c;卸载原来的docker 在命令行中运行&#xff1a; sudo apt-get updatesudo apt-get remove docker docker-engine docker.io containerd runc 安装docker依赖 apt-get…

饥荒Mod 开发(二一):超大便携背包,超大物品栏,永久保鲜

饥荒Mod 开发(二十)&#xff1a;显示打怪伤害值 饥荒Mod 开发(二二)&#xff1a;显示物品信息 源码 游戏中的物品栏容量实在太小了&#xff0c;虽然可以放在箱子里面但是真的很不方便&#xff0c;外出一趟不容易看到东西都不能捡。实在是虐心。 游戏中的食物还有变质机制&#…

SSTI模板注入基础(Flask+Jinja2)

文章目录 一、前置知识1.1 模板引擎1.2 渲染 二、SSTI模板注入2.1 原理2.2 沙箱逃逸沙箱逃逸payload讲解其他重要payload 2.3 过滤绕过点.被过滤下划线_被过滤单双引号 "被过滤中括号[]被过滤关键字被过滤 三、PasecaCTF-2019-Web-Flask SSTI参考文献 一、前置知识 1.1 模…

力扣:51. N 皇后

题目&#xff1a; 按照国际象棋的规则&#xff0c;皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题 研究的是如何将 n 个皇后放置在 nn 的棋盘上&#xff0c;并且使皇后彼此之间不能相互攻击。 给你一个整数 n &#xff0c;返回所有不同的 n 皇后问题 的…

多维时序 | MATLAB实现SSA-CNN-SVM麻雀算法优化卷积神经网络-支持向量机多变量时间序列预测

多维时序 | MATLAB实现SSA-CNN-SVM麻雀算法优化卷积神经网络-支持向量机多变量时间序列预测 目录 多维时序 | MATLAB实现SSA-CNN-SVM麻雀算法优化卷积神经网络-支持向量机多变量时间序列预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 多维时序 | MATLAB实现…

ubuntu22.04 下载路径

ftp下载路径 csdn下载 ubuntu22.04下载路径ubuntu-22.04-desktop-amd64.7z.001资源-CSDN文库 ubuntu22.04下载路径ubuntu-22.04-desktop-amd64.7z.002资源-CSDN文库 【免费】ubuntu-22.04-desktop-amd64.7z.003资源-CSDN文库 【免费】ubuntu-22.04-desktop-amd64.7z.004资源-…

大数据应用开发1——配置基础环境

一、基础环境配置 1.配置虚拟网络 1.1、点击1、编辑2和3&#xff0c; 1.2、点开4&#xff0c;编辑网关 2、配置虚拟机环境 1.1、安装一台虚拟机&#xff0c;使用root用户登录&#xff0c;打开终端 1.2修改主机名 终端输入&#xff1a; vim /etc/hostname使用vim编辑/etc/ho…

linux异步IO的几种方法及重点案例

异步IO的方法 在Linux下&#xff0c;有几种常见的异步I/O&#xff08;Asynchronous I/O&#xff09;机制可供选择。以下是其中一些主要的异步I/O机制&#xff1a; POSIX AIO&#xff08;Asynchronous I/O&#xff09;&#xff1a;POSIX AIO是一种标准的异步I/O机制&#xff0c…

三道C语言中常见的笔试题及答案(一)

题目一&#xff1a; 问题&#xff1a; 解释以下代码中的#define预处理指令的作用&#xff0c;并说明其优点和缺点。 #include <stdio.h> #define PI 3.14159 #define CALCULATE_AREA(r) (PI * r * r) int main() { double radius 5.0; double area CALCULATE_AREA(r…