Huffman编码与解码

Huffman编码与解码

// @author: Folivora Li
// @copyright Folivora Li

/*
4、Huffman编码与解码 (必做)(Huffman编码、二叉树)
[问题描述]
对一篇不少于5000字符的英文文章(source.txt),统计各字符出现的次数,
实现Huffman编码(code.dat),以及对编码结果的解码(recode.txt)。
[基本要求]
(1) 输出每个字符出现的次数和编码,并存储文件(Huffman.txt)。
(2) 在Huffman编码后,英文文章编码结果保存到文件中(code.dat),
编码结果必须是二进制形式,即0 1的信息用比特位表示,不能用字符’0’和’1’表示。
(3) 实现解码功能。
*/
#include <iostream>
#include <map>
#include <fstream>
#include <string.h>
#include <stdio.h>
using namespace std;
typedef struct {
	char character;
	int time;
}Character;

typedef struct binode
{
	Character data;
	binode* left;
	binode* right;
}BiTreeNode;

BiTreeNode** CreateBiNode(Character* a, int num)
{
	BiTreeNode** treenode = new BiTreeNode * [num];
	for (int i = 0; i < num; i++)
	{
		treenode[i] = new BiTreeNode;
	}
	for (int i = 0; i < num; i++)
	{
		treenode[i]->left = NULL;
		treenode[i]->right = NULL;
		treenode[i]->data = a[i];

	}
	return treenode;
}
void CreateHuffmanTree(BiTreeNode**& treenode, int& num)
{
	BiTreeNode* min1 = treenode[0];
	BiTreeNode* min2 = treenode[1];
	int min1serial = 0;
	int min2serial = 1;
	//min1最小,min2次小
	for (int i = 1; i < num; i++)
	{
		if (min1->data.time > treenode[i]->data.time)
		{
			min1 = treenode[i];
			min1serial = i;
		}

	}
	if (min1serial == 1)
	{
		min2 = treenode[0];
		min2serial = 0;
	}
	for (int i = 0; i < num; i++)
	{
		if (min2->data.time > treenode[i]->data.time)
		{
			if (i != min1serial)
			{
				min2 = treenode[i];
				min2serial = i;
			}
		}
	}
	//两树合成
	BiTreeNode* newtreenode = new BiTreeNode;
	newtreenode->data.time = min1->data.time + min2->data.time;
	newtreenode->data.character = ' ';
	newtreenode->left = min1;
	newtreenode->right = min2;
	treenode[min1serial] = newtreenode;
	BiTreeNode* temp = treenode[min2serial];
	treenode[min2serial] = treenode[num - 1];
	num--;
	//cout << min1serial << " " << min2serial << " " << endl;


}


BiTreeNode* ReturnHuffmanTree(BiTreeNode**& treenode, int num)
{
	while (num > 1)
	{
		CreateHuffmanTree(treenode, num);
	}
	return treenode[0];
}
void PreOrderTraverse(BiTreeNode* root)
{
	if (root == NULL)
	{
		return;
	}
	cout << root->data.character << "  ";
	if (root->left != NULL)
	{
		PreOrderTraverse(root->left);
	}
	if (root->right != NULL)
	{
		PreOrderTraverse(root->right);
	}
}
void Encode(BiTreeNode* root,int* a, int length)
{
	if (root == NULL)
	{
		return;
	}
	if ((root->left == NULL) && (root->right == NULL))
	{
		fstream file;
		file.open("D:\\code.dat", ios::app|ios::out);
		cout << root->data.character << "的编码是:";
		for (int i = 0; i <length; i++)
		{
			cout << a[i];
			file << a[i];
		}
		file.close();
		cout << endl;
		return;

	}
	if (root->left != NULL)
	{
		a[length] = 0;
		Encode(root->left, a, length + 1);
	}
	if (root->right != NULL)
	{
		a[length] = 1;
		Encode(root->right, a, length + 1);
	}
}

void Decode(BiTreeNode* root,BiTreeNode* Trueroot, char* a, int length,int serial,fstream& file,int& judge)
{
	if (judge == 1)
	{
		return;
	}
	if ((root->left == NULL) && (root->right == NULL))
	{
		cout << "解码后的字符是:" << root->data.character << endl;
		file << "解码后的字符是:";
		file << root->data.character;
		file << '\n';
		if (length - 1 > serial)
		{
			Decode(Trueroot, Trueroot, a, length, serial, file, judge);
		}
		else
		{
			judge = 1;
			return;
		}

	}
	if (a[serial] == '0')
	{
		if (judge == 1)
		{
			return;
		}
		cout << 0;
		file << '0';
		Decode(root->left, Trueroot, a, length, serial + 1, file, judge);
		if (judge == 1)
		{
			return;
		}
	}
	if (a[serial] == '1')
	{
		if (judge == 1)
		{
			return;
		}
		cout << 1;
		file << '1';
		Decode(root->right, Trueroot, a, length, serial + 1, file, judge);
		if (judge == 1)
		{
			return;
		}
	}
}
int main()
{
	fstream file1;
	file1.open("D:\\source.txt", ios::in);
	if (file1.fail())
	{
		cout << "error" << endl;
		exit(1);
	}
	map<char, int>mapHuffman;
	map<char, int>::iterator iter;
	map<char, int>::iterator iter1;
	char name;
	int num = 0;
	while (!file1.eof())
	{
		file1 >> name;
		iter = mapHuffman.find(name);
		if (iter == mapHuffman.end())
		{
			mapHuffman.insert(pair<char, int>(name, 0));
			num++;
		}
		else
		{
			iter->second++;
		}
	}
	file1.close();
	for (iter1 = mapHuffman.begin(); iter1 != mapHuffman.end(); iter1++)
	{
		cout << iter1->first << ":" << iter1->second << endl;
	}
	Character* Container = new Character[num];
	int i = 0;
	for (iter = mapHuffman.begin(); iter != mapHuffman.end(); iter++, i++)
	{
		Container[i].character = iter->first;
		Container[i].time = iter->second;
	}
	BiTreeNode** treenode = CreateBiNode(Container, num);
	BiTreeNode* huffmantree = ReturnHuffmanTree(treenode, num);
	
	//PreOrderTraverse(huffmantree);
	int* a = new int[20];
	Encode(huffmantree, a, 0);
	char b[5000];
	fstream file2;
	file2.open("D:\\code.dat", ios::in);
	if (file2.fail())
	{
		cout << "error" << endl;
		exit(1);
	}
	int count = 0;
	char c;
	while (!file2.eof())
	{
		file2 >> c;
		b[count++] = c;
	}
	fstream file;
	file.open("D:\\decode.txt", ios::out);
	int judge = 0;
	Decode(huffmantree, huffmantree, b, count, 0, file,judge);
	remove("D:\\code.dat");
}
  • 0
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值