功能
Txt.txt 需要自己建立(保存英文文本)并放在和.cpp文件同个文件夹,都放在在桌面也可以。
1、 可以读取所有英文字符
2、自动计算文本中所有字符的 编码 和 权重 (字符在文件中出现次数) 保存在HuffmanCode.txt文件中
3、能将文本按照编码加密并将得到的加密文本 TxtToHu.txt,并用哈夫曼树再翻译为文本 HuToTxt.txt
4、除了Txt.txt文件需要自己建立,其他文件程序自动建立
完整代码
#include <iostream>
#include <stdlib.h>
#include <fstream>
#include <string>
using namespace std;
int NumOfChar;//字符种类
int MaxSize; //静态链表实际使用大小 MAxsize-1也是哈夫曼树根结点的下标
const int MaxLen = 257;//256+1
typedef int Int;
typedef struct Node{
int weight;//字符对应权重
char c;//字符类型
Int parent,lchild,rchild;//双亲指针,左右孩子指针
}HTNode;
HTNode Hu[MaxLen*2];//哈夫曼树结点数为2*n-1
typedef struct HuCode{
string code;
}HNode;
HNode HfCode[MaxLen];//用来存储哈夫曼编码
int Caculate[MaxLen];
void Get_CharInfo(void){
//从文件中计算字符种类和权值
ifstream in;
in.open("Txt.txt");
char c;
while(in.get(c)){
//不到达文件末尾的情况下读取字符
Caculate[c] ++;//将读到的字符对应权重+1
}
NumOfChar = 0;
for(int i = 0;i < MaxLen;i++)
if(Caculate[i]){
//如果权重不为0
Hu[++NumOfChar].c = i;//存字符
Hu[NumOfChar].weight = Caculate[i]; //存权重
}
MaxSize = NumOfChar*2-1;//得到实际的哈夫曼树结点数量
in.close();//关闭文件
return;
}
void Creat_HuffmanTree(void){
//建立哈夫曼树
int low1 = 0,low2 = 0;
int indexofParent = NumOfChar+1;//第一个双亲结点下标
while(1){
//找到权重最低的两个结点
low1 = low2 = 0;
for(int i = 1;i < indexofParent;i++){
//找low1
if(!low1 && !Hu[i].parent){
//还没找到
low1 = i;
}else if(low1 && !Hu[i].parent && Hu[low1].weight > Hu[i].weight){
low1 = i;
}
}
for(int i = 1;i < indexofParent;i++){
if(i!=low1){
if(!low2 && !Hu[i].parent){
//找low2
low2 = i;
}else if(low2 && !Hu[i].parent && Hu[low2].weight > Hu[i].weight){
low2 = i;
}
}
}
Hu[indexofParent].weight = Hu[low1].weight + Hu[low2].weight;//计算双亲结点的权重值
Hu[indexofParent].lchild = low1;
Hu[indexofParent].rchild = low2;
Hu[low1].parent = indexofParent;
Hu[low2].parent = indexofParent;//low2为0 ???? 时indexofParent = 8指针越界
if(indexofParent == MaxSize){
//如果哈夫曼树已经构建完成就退出
break; //已经构建 MaxSize个结点
}
indexofParent++;//下个父节点位置
}
return;
}
void Create_Huffman_Code(int index,string scode){
//通过哈夫曼树建立哈夫曼编码
//index 初始值为根结点
if(Hu[index].lchild){
//说明该结点不是叶子结点
scode.append("0");
Create_Huffman_Code(Hu[index].lchild,scode);
scode = scode.substr(0,scode.length()-1);//删除末尾元素 向右子树搜索
scode.append("1");
Create_Huffman_Code(Hu[index].rchild,scode);
}
else HfCode[(int)(Hu[index].c)].code = scode;//否则该字符完成编码
return;
}
void Print_HuffmanCodeToFile(void){
//将 字符 权重 编码 输入到文件中
ofstream in;
in.open("HuffmanCode.txt");
for(int i = 1;i <= NumOfChar;i++){
in << "字符:" << Hu[i].c << " 权重:" << Hu[i].weight << " 编码:" <<HfCode[Hu[i].c].code<<endl;
}
in.close();
return;
}
void Txt_To_Huffmantxt(void){
//文本转哈夫曼编码
ifstream in;
in.open("Txt.txt");
ofstream out;
out.open("TxtToHu.txt");
char c;
while(in.get(c)){
out << HfCode[(int)c].code;
}
in.close();
out.close();
return;
}
void HuffmantxtToTxt(void){
//哈夫曼编码转文本
ifstream in;
in.open("TxtToHu.txt");
ofstream out;
out.open("HuToTxt.txt");
char c;
int index = MaxSize;
while(in.get(c)){
if(c == '1'){
//1
if(Hu[Hu[index].rchild].rchild){
//如果指向的结点不是叶子结点
index = Hu[index].rchild;//通过该结点是否有孩子来判断
}else{
//是叶子结点
out << Hu[Hu[index].rchild].c;
index = MaxSize;//回到根结点
}
}else{
//0
if(Hu[Hu[index].lchild].lchild){
index = Hu[index].lchild;
}else{
out << Hu[Hu[index].lchild].c;
index = MaxSize;
}
}
}
in.close();
out.close();
return;
}
int main(){
string scode = "";//string 赋空
Get_CharInfo();//获取字符和权值
Creat_HuffmanTree();//建立哈夫曼树
Create_Huffman_Code(MaxSize,scode);//建立哈夫曼编码
Print_HuffmanCodeToFile(); //将设计的编码输出到文件中
Txt_To_Huffmantxt();//通过查找字符对应的编码 将文本转换为编码文件
HuffmantxtToTxt();//通过哈夫曼树 将编码文件转换为文本。
//system("pause");
return 0;
}