Huffman树的实现C++

具体功能:

  1. 将给定字符文件编码,生成编码,输出每个字符出现的次数和编码;
  2. 将给定编码文件译码,生成字符,输出编码及其对应字符。

文件说明:

  1. 文件名为inputfile1.txt的文件保存的是一段英文短文;
  2. 文件名为inputfile2.txt的文件保存01形式的编码段;
  3. 文件名为outputfile1.txt的文件保存各字符的出现次数和对应的编码;
  4. 文件名为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;
}

猜你喜欢

转载自blog.csdn.net/Hodge_Z/article/details/84344634