具体功能:
- 将给定字符文件编码,生成编码,输出每个字符出现的次数和编码;
- 将给定编码文件译码,生成字符,输出编码及其对应字符。
文件说明:
- 文件名为inputfile1.txt的文件保存的是一段英文短文;
- 文件名为inputfile2.txt的文件保存01形式的编码段;
- 文件名为outputfile1.txt的文件保存各字符的出现次数和对应的编码;
- 文件名为outputfile2.txt的文件保存对应于inputfile2.txt的译码结果。
实现:
统计inputfile1.txt中各字符的出现频率,并据此构造霍夫曼树,编制霍夫曼码;根据已经得到的编码,对01形式的编码段进行译码。
#include <iostream> #include <algorithm> #include <cstring> #include<string> #include <fstream> using namespace std; #define MAXBIT 100 //存放编码 #define MAXVALUE 1000000 //为后面选取权值最小的两个结点 #define MAXLEAF 30 //叶子结点数 #define MAXNODE MAXLEAF*2-1 //结点总数 typedef struct { double weight; int parent, lchild, rchild; char value; }HNodeType; typedef struct { int bit[MAXBIT]; int start; }HCodeType; HNodeType HuffNode[MAXNODE];//定义一个结点结构体数组 HCodeType HuffCode[MAXLEAF];// 定义一个编码结构体数组 extern int Count=0;//统计字符的种类数 extern int cnt[256] = {};//ascii总共256个,记录字符出现频数 //获取文本信息---字符种类数,频数 void GetInfo() { string str; ifstream inFile("inputfile1.txt");//读取文本文件 getline(inFile, str); for (unsigned int i = 0; i < str.length(); i++) { cnt[(int)(tolower(str[i]))]++;//不区分大小写 tolower函数转换成小写 if (cnt[(int)(tolower(str[i]))] == 1) { Count++; } } inFile.close(); } //构建哈夫曼树 void HuffmanTree(HNodeType HuffNode[MAXNODE], int arr[], int n) { int i, j, z, p1, p2;//p1,p2哈夫曼树过程中最小的两个权值数组的下标 double min1, min2;//哈夫曼树过程中最小的两个权值 for (i = 0; i<n; i++) //初始化 { HuffNode[i].weight = 0; HuffNode[i].parent = -1; HuffNode[i].lchild = -1; HuffNode[i].rchild = -1; } //输入n个叶子的权值 z = 0; for (i = 0; i<256; i++) { if (arr[i] != 0) { HuffNode[z].value = (char)i; HuffNode[z].weight = arr[i]; z++; } } //构建哈夫曼树 for (i = 0; i<n - 1; i++) { min1 = min2 = MAXVALUE; p1 = p2 = 0; for (j = 0; j<n + i; j++) { if (HuffNode[j].weight<min1 && HuffNode[j].parent == -1) { min2 = min1; p2 = p1; min1 = HuffNode[j].weight; p1 = j; } else if (HuffNode[j].weight < min2 && HuffNode[j].parent == -1) { min2 = HuffNode[j].weight; p2 = j; } } HuffNode[p1].parent = n + i; HuffNode[p2].parent = n + i; HuffNode[n + i].parent = -1; //构建一个新根 HuffNode[n + i].weight = min1 + min2; HuffNode[n + i].lchild = p1; HuffNode[n + i].rchild = p2; } } //哈夫曼编码 void HuffmanCode(HCodeType HuffCode[MAXLEAF], int n) { HCodeType temp;//定义临时变量 int i, j, c, p; for (i = 0; i<n; i++) { temp.start = n - 1; c = i; p = HuffNode[c].parent; while (p != -1) { if (HuffNode[p].lchild == c) temp.bit[temp.start] = 0; else temp.bit[temp.start] = 1; temp.start--; c = p; p = HuffNode[c].parent; } for (j = temp.start + 1; j<n; j++) // 把叶子结点的编码信息从临时变量中复制出来,放入编码结构体数组 HuffCode[i].bit[j] = temp.bit[j]; HuffCode[i].start = temp.start; } //输出结果 ofstream outFile("outputfile1.txt"); outFile << "字符\t" << "出现次数\t" << "对应的编码" << endl; for (i = 0; i<n; i++) { outFile << HuffNode[i].value << "\t" << HuffNode[i].weight<<"\t\t"; for (j = HuffCode[i].start + 1; j<n; j++) outFile << HuffCode[i].bit[j]; outFile << endl; } outFile.close(); } //哈夫曼译码操作 void HuffmandeCode(int count) { string arr; ifstream inFile("inputfile2.txt"); getline(inFile, arr); ofstream outFile("outputfile2.txt"); int j = count * 2 - 2; for (unsigned int i = 0; i < arr.length(); i++) { if (arr[i] == '0') { j = HuffNode[j].lchild; } else if (arr[i] == '1') { j = HuffNode[j].rchild; } if (HuffNode[j].lchild == -1 && HuffNode[j].rchild == -1) { outFile<< HuffNode[j].value;//写入文本 j = count * 2 - 2; } } inFile.close(); outFile.close(); } int main() { GetInfo();//获取文本信息 HuffmanTree(HuffNode, cnt, Count);//构建哈夫曼树 HuffmanCode(HuffCode, Count);//编码 HuffmandeCode(Count);//译码 return 0; }