【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.hqwc.cn/news/298975.html

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

相关文章

Schmitt Trigger本质就是一个带迟滞的比较器

Chapter 18 Special Purpose CMOS Circuits 甚高 24 人赞同了该文章 Chapter 18 Special Purpose CMOS Circuits 这一章讲几个实用电路, Schmitt trigger 输入信号noisy, 输出产生干净的pulse. 然后介绍multivibrator, 拥有astable和monostable两态. input buffer design 对…

【MySQL索引特性】

目录&#xff1a; 前言引入认识磁盘MySQL与存储 索引的理解理解单个Page理解多个Page引入B树结构聚簇索引 VS 非聚簇索引 索引操作创建主键索引唯一索引的创建普通索引的创建查看索引删除索引 总结 前言 剑指offer&#xff1a;一年又10天 引入 索引&#xff0c;是用来提高查询…

教你如何开发并运营小程序商城或APP商城!

随着线下租金、仓储等成本的攀升&#xff0c;商家们面临着越来越大的压力。为了降低成本、提高效率&#xff0c;越来越多的商家开始转型做电商&#xff0c;甚至直接开发自己的电商商城小程序或APP。那么&#xff0c;商城小程序或APP该如何开发呢&#xff1f;又该如何运营呢&…

深度学习中的Dropout

1 Dropout概述 1.1 什么是Dropout 在2012年&#xff0c;Hinton在其论文《Improving neural networks by preventing co-adaptation of feature detectors》中提出Dropout。当一个复杂的前馈神经网络被训练在小的数据集时&#xff0c;容易造成过拟合。为了防止过拟合&#xff…

golang基于window下实现文件遍历(效率高于filepath.Wlak)

golang基于window下实现文件遍历(效率高于filepath.Wlak) package mainimport ("fmt""os""path""path/filepath""syscall""time""unsafe" )const MAX_PATH 260type FILETIME struct {dwLowDateTime …

千帆起航:探索百度智能云千帆AppBuilder在AI原生应用开发中的革新之路

千帆起航&#xff1a;探索百度千帆AppBuilder在AI原生应用开发中的革新之路 1.揭开帷幕&#xff0c;大模型第二次战役 自从 ChatGPT 横空出世后&#xff0c;一石激起千层浪&#xff0c;人工智能也正在从感知理解走向生成创造&#xff0c;这是一个关键里程碑。生成式大模型完成…

视觉学习(5) —— 绑定流程

1、前提 2、接收事件 绑定参数 3、规则列表的设置 &#xff08;1&#xff09;字节起止位置 0到1是两个字节 当输入值为整数1 &#xff08;2&#xff09;比较规则配置 大于 等于 小于 上升沿等等 而后是范围 值等于1到5之间都算满足条件 4、全局触发 以上的逻辑&#xff1a;当…

HBase基础知识(五):HBase 对接 Hadoop 的 MapReduce

通过 HBase 的相关 JavaAPI&#xff0c;我们可以实现伴随 HBase 操作的 MapReduce 过程&#xff0c;比如使用 MapReduce 将数据从本地文件系统导入到 HBase 的表中&#xff0c;比如我们从 HBase 中读取一些原 始数据后使用 MapReduce 做数据分析。 1 官方 HBase-MapReduce 1&am…

猫头虎分享2023年12月17日博客之星候选--领域赛道博主文章数据

猫头虎分享2023年12月17日博客之星候选–领域赛道博主文章数据 博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开…

浅谈Dubbo核心概念及架构流程

浅谈Dubbo核心概念及架构流程 前言重要概念1、SPI2、ServiceBean3、URL4、Invoker 整体流程1、架构图2、调用链路 笔者碎碎言&#xff0c;我们学习Dubbo应该学的是什么&#xff1f; 笔者是一名业务开发&#xff0c;认为一切目的都要为我们的目标服务&#xff0c;即日常工作有帮…

从零实现一套低代码(保姆级教程) --- 【5】实现组件和属性面板的交互

摘要 在上一篇中&#xff0c;我们简单实现了右侧属性面板。可以通过更改按钮文字&#xff0c;重新渲染Button组件。 目前来到了本系列的第五章&#xff0c;本篇主要是实现Button组件的全部属性配置。 如果你是第一次看本系列中的文章&#xff0c;建议可以先看一下第一节&…

【adb】电脑通过ADB向手机传输文件

具体步骤如下&#xff1a; Step1 下载ADB工具 下载最新版本的 ADB工具 !!! 注意&#xff1a;一定要是最新版本的ADB&#xff0c;否则很可能导致无法识别到手机。 将下载的ADB解压以后的文件如下图所示&#xff1a; Step2 添加环境变量 将 ADB的路径 D:\platformtools &…