一、目的与任务
1.目的:掌握赫夫曼(Huffman)树和赫夫曼编码的基本思想和应用。
2.任务:实现文件中数据的加解密与压缩。
二、内容、要求与安排方式
1.实验内容:将硬盘上的一个文本文件进行加密,比较加密文件和原始文件的大小差别;对加密文件进行解密,比较原始文件和解码文件的内容是否一致。
2.输入和输出:
(1)输入:硬盘上给定的原始文件及文件路径。
(2)输出:
硬盘上的加密文件及文件路径;
硬盘上的解码文件及文件路径;
原始文件和解码文件的比对结果。
3.实验要求:
提取原始文件中的数据(包括中文、英文或其他字符),根据数据出现的频率为权重,构建Huffman编码表;
根据Huffman编码表对原始文件进行加密,得到加密文件并保存到硬盘上;
将加密文件进行解密,得到解码文件并保存点硬盘上;
比对原始文件和解码文件的一致性,得出是否一致的结论。
输出文件路径有点懒了。。。
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef struct Tree *HuffmanTree;
struct point
{
char c;
int weight;
bool leaf;
};
struct Tree
{
struct point Date;
Tree *Lt, *Rt;
void set_date(char c, int weight, bool leaf, HuffmanTree Lt, HuffmanTree Rt)
{
this->Date.c = c;
this->Date.weight = weight;
this->Date.leaf = leaf;
this->Lt = Lt;
this->Rt = Rt;
}
};
struct cmp
{
bool operator () (HuffmanTree a, HuffmanTree b)
{
return a->Date.weight > b->Date.weight;
}
};
void in_it();
HuffmanTree CreateHuffmanTree();
void CreateHuffmanTable(HuffmanTree T, string code);
void ShowTable();
void Coding();
void Decoding();
priority_queue<HuffmanTree, vector<HuffmanTree>, cmp> valueQueue;//
map<string, char> codeToValue;//编码对字符的映射
char path[200];
int main()
{
in_it();
HuffmanTree Root = (HuffmanTree)malloc(sizeof(struct Tree));
Root = CreateHuffmanTree();
CreateHuffmanTable(Root, "");
ShowTable();
Coding();
Decoding();
}
void in_it()
{
map<char, int> valueToNum;//字符和数量的映射
printf("输入文件路径\n");
cin >> path;
ifstream text(path, ios::in);
while(!text.eof())
{
char ch;
text.get(ch);
if(text.fail())
break;
cout << ch;
if(valueToNum.find(ch) == valueToNum.end())
valueToNum[ch] = 1;
else
valueToNum[ch] += 1;
}
text.close();
putchar('\n');
map<char, int>::iterator i;
for(i = valueToNum.begin(); i != valueToNum.end(); i++)
{
if(i->first == -1)
continue;
HuffmanTree leaf = (HuffmanTree)malloc(sizeof(struct Tree));;
leaf->set_date(i->first, i->second, true, NULL, NULL);
valueQueue.push(leaf);
}
}
HuffmanTree CreateHuffmanTree()
{
HuffmanTree root;
while(!valueQueue.empty())
{
HuffmanTree L = (HuffmanTree)malloc(sizeof(struct Tree));
L = valueQueue.top();
valueQueue.pop();
if(L->Date.c == '\n')
printf("%s\t%d\n", "\\n", L->Date.weight);
else if(L->Date.c == ' ')
printf("%s\t%d\n", "Space", L->Date.weight);
else
printf("%c\t%d\n", L->Date.c, L->Date.weight);
if(!valueQueue.empty())
{
HuffmanTree R = (HuffmanTree)malloc(sizeof(struct Tree));
R = valueQueue.top();
valueQueue.pop();
if(R->Date.c == '\n')
printf("%s\t%d\n", "\\n", R->Date.weight);
else if(R->Date.c == ' ')
printf("%s\t%d\n", "Space", R->Date.weight);
else
printf("%c\t%d\n", R->Date.c, R->Date.weight);
root = (HuffmanTree)malloc(sizeof(struct Tree));
root->set_date('\0', L->Date.weight+R->Date.weight, false, L, R);
valueQueue.push(root);
}
else
{
root = L;
break;
}
}
putchar('\n');
return root;
}
void CreateHuffmanTable(HuffmanTree T, string code)
{
if(T->Date.leaf == true)
{
codeToValue[code] = T->Date.c;
return;
}
CreateHuffmanTable(T->Lt, code + "0");
CreateHuffmanTable(T->Rt, code + "1");
return;
}
void ShowTable()
{
printf("编 码 表\n");
ofstream table("table.txt", ios::out);
map<string, char>::iterator i;
for(i = codeToValue.begin(); i != codeToValue.end(); i++)
{
if(i->second == '\n')
{
cout << i->first+'\t'+'\t' << "\\n" << '\n';
table << i->first+'\t'+'\t' << "\\n" << '\n';
}
else if(i->second == ' ')
{
cout << i->first+'\t'+'\t' << "Space" << '\n';
table << i->first+'\t'+'\t' << "Space" << '\n';
}
else
{
cout << i->first+'\t'+'\t' << i->second << '\n';
table << i->first+'\t'+'\t' << i->second << '\n';
}
}
printf("%s%s\n", "文件保存在:", "E:\\Code\\Huffman\\table.txt");
putchar('\n');
}
void Coding()
{
printf("Coding......\n");
ifstream text(path, ios::in);
ofstream coding("coding.txt", ios::out);
while(!text.eof())
{
char ch;
text.get(ch);
if(text.fail())
break;
//text >> ch;
map<string, char>::iterator i;
for(i = codeToValue.begin(); i != codeToValue.end(); i++)
{
if(i->second == ch)
{
coding << i->first;
cout << i->first;
//coding << endl;
break;
}
}
}
text.close();
coding.close();
putchar('\n');
printf("%s%s\n\n", "文件保存在:", "E:\\Code\\Huffman\\coding.txt");
}
void Decoding()
{
printf("DeCoding......\n");
ifstream coding("coding.txt", ios::in);
ofstream decoding("decoding.txt", ios::out);
string tool;
while(!coding.eof())
{
char ch;
coding >> ch;
if(coding.fail())
break;
tool = tool + ch;
if(codeToValue.find(tool) != codeToValue.end())
{
decoding << codeToValue[tool];
cout <<codeToValue[tool];
tool = "";
}
//Sleep(1);
}
coding.close();
decoding.close();
putchar('\n');
printf("%s%s\n\n", "文件保存在:", "E:\\Code\\Huffman\\decoding.txt");
}