数据结构——Huffman编码及译码

Huffman编码及译码

1.掌握二叉树的二叉链表存贮结构。

2.掌握Huffman算法。

 

要求:

使用文件保存初始的文本数据及最终的结果。

  1. 文件名为inputfile1.txt的文件保存的是一段英文短文;
  2. 文件名为inputfile2.txt的文件保存01形式的编码段;
  3. 文件名为outputfile1.txt的文件保存各字符的出现次数和对应的编码;
  4. 文件名为outputfile2.txt的文件保存对应于inputfile2.txt的译码结果。

统计inputfile1.txt中各字符的出现频率,并据此构造Huffman树,编制Huffman 码;根据已经得到的编码,对01形式的编码段进行译码。

具体的要求:

1.将给定字符文件编码,生成编码,输出每个字符出现的次数和编码;

2.将给定编码文件译码,生成字符,输出编码及其对应字符。

 

输入数据格式:

详见要求部分。

 

输出数据格式:

outputfile1.txt文件中:

字符  出现次数  对应的编码

 a      37         010

 b      130        00

 

outputfile2.txt文件中:

This is a example.

 

 

分析(如何构造哈夫曼树):

假设有n个权值,则构造出的哈夫曼树有n个叶子结点。 n个权值分别设为 w1、w2、…、wn,则哈夫曼树的构造规则为:


(1) 将w1、w2、…,wn看成是有n 棵树的森林(每棵树仅有一个结点);


(2) 在森林中选出两个根结点的权值最小的树合并,作为一棵新树的左、右子树,且新树的根结点权值为其左、右子树根结点权值之和;


(3)从森林中删除选取的两棵树,并将新树加入森林;


(4)重复(2)、(3)步,直到森林中只剩一棵树为止,该树即为所求得的哈夫曼树。

 

 如:对 下图中的六个带权叶子结点来构造一棵哈夫曼树,步骤如下(借用一下他人好看的图):

 

代码如下(vs2012):

#include<iostream>
#include<fstream>
#include<string>
using namespace std;
struct Huffmannode {
	int parent;
	int lc;
	int rc;
	int weight;
};
class Huffmantree {
private:
	Huffmannode*node;
	char* letter;
	int leafnum;
public:
	Huffmantree();
	~Huffmantree();
	Huffmannode*Initialization(int sum, char z[], int w[]);
	void Encord(Huffmannode*node, char tree[], int sum, char z[], int w[]);
	void Decord(Huffmannode*node, int sum, char z[]);
};
Huffmantree::Huffmantree() {
	node = NULL;
	letter = NULL;
	leafnum = 0;
}
Huffmantree::~Huffmantree() {
	delete[]node;
	delete[]letter;
}
Huffmannode*Huffmantree::Initialization(int sum, char z[], int w[]) {
	int min1, min2;
	int loc1, loc2;
	node = new Huffmannode[2 * sum - 1];
	letter = new char[2 * sum - 1];
	for (int i = 0; i<sum; i++) {
		letter[i] = z[i];
		node[i].weight = w[i];
		node[i].parent = -1;
		node[i].lc = -1;
		node[i].rc = -1;
	}
	for (int i = sum; i<2 * sum - 1; i++) {
		loc1 = -1;
		loc2 = -1;
		min1 = 32767;
		min2 = 32767;
		for (int j = 0; j<i; j++) {
			if (node[j].parent == -1) {
				if (node[j].weight<min1) {
					min2 = min1;
					min1 = node[j].weight;
					loc2 = loc1;
					loc1 = j;
				}
				else {
					if (node[j].weight<min2) {
						min2 = node[j].weight;
						loc2 = j;
					}
				}
			}
		}
		node[loc1].parent = i;
		node[loc2].parent = i;
		node[i].lc = loc1;
		node[i].rc = loc2;
		node[i].parent = -1;
		node[i].weight = node[loc1].weight + node[loc2].weight;
	}
	return node;
}
void Huffmantree::Encord(Huffmannode*node, char t[], int sum, char z[], int w[]) {
	char* code;
	code = new char[sum];
	int m = 0;
	int i, n = 0;
	ofstream shuchu;
	shuchu.open("outputfile1.txt", ios::app);
	while (z[n] != '\0') {
		int r, k = 0, q;
		r = n;
		q = n;
		shuchu << z[n] << "   " << w[n] << "   ";
		while (node[r].parent != -1) {
			r = node[r].parent;
			if (node[r].lc == q) {
				code[k] = '0';
				k++;
			}
			else {
				code[k] = '1';
				k++;
			}
			q = r;
		}
		code[k] = '\0';
		k -= 1;
		while (k >= 0) {
			shuchu << code[k];
			k--;
		}
		shuchu << '\n';
		n++;
	}
	shuchu.close();
	ofstream out;
	out.open("inputfile2.txt", ios::app);
	while (t[m] != '\0') {
		int j, s = 0;
		for (i = 0; i<sum; i++) {
			if (t[m] == z[i])break;
		}
		j = i;
		while (node[j].parent != -1) {
			j = node[j].parent;
			if (node[j].lc == i) {
				code[s] = '0';
				s++;
			}
			else {
				code[s] = '1';
				s++;
			}
			i = j;
		}
		code[s] = '\0';
		s -= 1;
		while (s >= 0) {
			out << code[s];
			s--;
		}
		m++;
	}
	out.close();
}
void Huffmantree::Decord(Huffmannode *node, int sum, char z[]) {
	ifstream tree("inputfile2.txt");
	int k = 0;
	char *code = new char[1000];
	while (!tree.eof()) {
		tree >> code[k];
		k++;
	}
	code[k] = '\0';
	tree.close();
	ofstream yima("outputfile2.txt", ios::app);
	k = 0;
	int j = 2 * sum - 1 - 1;
	while (code[k + 1] != '\0') {
		if (code[k] == '0') {
			j = node[j].lc;
		}
		if (code[k] == '1') {
			j = node[j].rc;
		}
		if (node[j].lc == -1) {
			yima << z[j];
			j = 2 * sum - 1 - 1;
		}
		k++;
	}
	yima.close();
}
int main() {
	ifstream in("inputfile1.txt", ios::app);
	char tree[1000] = { 0 };
	char letter[100];
	int count[100] = { 0 };
	int i = 0, t = 0;
	while (!in.eof()) {
		tree[t] = in.get();
		t++;
	}
	tree[t] = '\0';
	int k = 0;
	in.close();
	while (tree[i] != '\0') {
		int m = 0;
		for (int j = 0; j<k; j++) {
			if (tree[i] == letter[j]) {
				count[j]++;
				m = 1;
			}
		}
		if (m == 0) {
			letter[k] = tree[i];
			count[k]++;
			k++;
		}
		i++;
	}
	count[k] = '\0';
	letter[k] = '\0';
	Huffmantree tree1;
	Huffmannode*node = tree1.Initialization(k, letter, count);
	tree1.Encord(node, tree, k, letter, count);
	tree1.Decord(node, k, letter);
}

 

  • 6
    点赞
  • 52
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值