Huffman编码(伪文件编码,用字符存编码)

老师要求的编码= =,好吧,那树打印的确实很丑...

 

首先是Huffman定义:

#include<string>
#include<map>
#include<bitset>
using namespace std;
struct HNode
{
	//数据
	double weight;
	char alp;
	string code;
	HNode *lchild,*rchild,*parent;
	//构造函数
	HNode():lchild(NULL),rchild(NULL),parent(NULL),weight(0.00),alp('@'),code(" "){}
	bool friend operator < (const HNode &R1,const HNode &R2)
	{
		return R1.weight>R2.weight;
	}
};
class HTree
{
public:
	HTree():num(0),root(NULL){}
	void Print();
	void input();
	void Tree();
	void codeprin();
	void Decoding();
	void Inorder(HNode *);
	void creat(HNode [],int);
	~HTree()
	{
		deltree(root);
	}
protected:
	HNode *root;
	int num;
	void printree(int ,HNode *);
	HNode node[128];
	map<char,string> Map;
	void setcode(string,HNode *);
	void deltree(HNode *); //删除子树
	void merge(HNode &,HNode &,HNode *&);//合并二叉树
};


 再者是Huffman实现:

#include"Huffman.h"
#include<queue>
#include<fstream>
#include<iostream>
using namespace std;
void HTree::creat(HNode w[],int n)//生成树
{
	priority_queue<HNode> que;
	int k=n;
	while(k)
		que.push(w[n-k--]);
	HNode *parent,*first,*second;//对象是直接用栈分配出来,不是动态分配出来的都是栈(预先分配好的内存,释放后和压入都是在同一个地方)
	for(int i=0;i<n-1;i++)
	{
		first = new HNode;// 堆分配出来的内存(随即分配和释放内存)
		second = new HNode;
		*first=que.top();
		que.pop();
		*second=que.top();
		que.pop();
		merge(*first,*second,parent);
		que.push(*parent);
	}
	root=parent;
	string pcode;
	setcode(pcode,root);//编码
	Inorder(root);//建立映射
}
void HTree::Tree()
{
	printree(0,root);
}
void HTree::Print()//打印到显示器
{
	ifstream infile;
	ofstream outfile;
	char c;
	int k=1;
	infile.open("CodePrin.txt");
	outfile.open("CodeFile.txt");
	if(!infile)
		cerr<<"文件打开失败"<<endl;
	if(!outfile)
		cerr<<"文件打开失败"<<endl;
	while(1)
	{
		infile>>c;
		if(!infile)
			break;
		cout<<c;
		outfile<<c;
		if(k++%50==0)
		{
			cout<<endl;
			outfile<<'\n';
		}
	}
	cout<<endl;
	infile.close();
}
void HTree::setcode(string code,HNode *node)//编码
{
	if(node)
	{
		code+='0';
		setcode(code,node->lchild);
		if(node->lchild)
		node->lchild->code=code;
		code[code.size()-1]='1';
		setcode(code,node->rchild);
		if(node->rchild)
		node->rchild->code=code;
	}
}
void HTree::Inorder(HNode *node)//建立Map映射
{
	if(node )
	{
		if(node->alp!='@')
			 Map[node->alp]=node->code;
		Inorder(node->lchild);
		Inorder(node->rchild);
	}
}
void HTree::codeprin()//E
{
	char c;
	int n=num;
	ofstream outfile,tfile;;
	ifstream infile;
	map<char,string>::iterator it;
	tfile.open("tree.bat");
	infile.open("ToBeTran.txt");	
	outfile.open("CodePrin.txt");
	if(!tfile)
			cerr<<"文件打开失败"<<endl;
	if(!outfile)
			cerr<<"文件打开失败"<<endl;
	if(!infile)
			cerr<<"文件打开失败"<<endl;
	while(n)
	{
		tfile.write((char *)&node[n-1],sizeof(node[n-1]));
		n--;
	}
	while(infile.get(c))
	{
		for(it=Map.begin();it!=Map.end();it++)
		{
			if((*it).first==c)
			{
				outfile<<Map[c];
				break;
			}
		}
	}
	outfile.close();
	infile.close();
	tfile.close();
}
void HTree::Decoding()//D
{
	ifstream infile;
	char c;
	string str;
	if(!num)
	{
		ifstream nfile;
		nfile.open("tree.bat");
		if(!nfile)
			cerr<<"文件打开失败"<<endl;
		while(1)
		{
			nfile.read((char *)&node[num],sizeof(node[num]));
			if(!nfile)
				break;
			num++;
		}
		creat(node,num);
	}
	map<char,string>::iterator it;
	infile.open("CodePrin.txt");
	ofstream outfile;
	outfile.open("Textfile.txt");
	if(!infile)
			cerr<<"文件打开失败"<<endl;
	if(!outfile)
			cerr<<"文件打开失败"<<endl;
	while(1)
	{
		infile>>c;
		str+=c;
		if(!infile)
			break;
		for(it=Map.begin();it!=Map.end();it++)
		{
			if((*it).second==str)
			{
				outfile<<(*it).first;
				str.clear();
				break;
			}
		}
	}
	infile.close();
	outfile.close();
}
void HTree::merge(HNode &t1,HNode &t2,HNode *&parent)//合并
{
	parent=new HNode;
	parent->lchild=&t1;
	parent->rchild=&t2;
	parent->weight=t1.weight+t2.weight;
	t1.parent=t2.parent=parent;
}
void HTree::deltree(HNode *node)//删除树
{
	HNode *p;
	while(node->rchild)
	{
		p=node;
		node=node->rchild;
		delete p->lchild;
		delete p;
	}
	delete node;
}
void HTree::input()
{
	int i;
	cout<<"输入出现字符种类的个数(为ToBeTran文件里的)"<<endl;
	cin>>num;
	cin.get();
	cout<<"输入字符的权,先输入字符再输入权(包括空格注意格式!)"<<endl
		<<"如:a 2.13"<<endl;
	for(i=0;i<num;i++)
	{
		cin.get(node[i].alp);
		cin>>node[i].weight;
		cin.get();
	}
	creat(node,num);
}
void HTree::printree(int ceng,HNode *node)
{
	if(node)
	{
		for(int i=0;i<ceng;i++)
			cout<<"    ";
		cout<<"|--->"<<node->alp<<endl;
		printree(ceng+1,node->lchild);
		printree(ceng+1,node->rchild);
	}
}


最后是主函数:

#include"Huffman.h"
#include<iostream>
using namespace std;
int main()
{
	HTree Tree;
	char c;
	while(1)
	{
		cout<<"I:初始化"<<endl
			<<"E:编码"<<endl
			<<"D:译码"<<endl
			<<"P:印代码文件"<<endl
			<<"T:打印树(目录结构)"<<endl
			<<"Q:离开"<<endl;
		cin>>c;
		switch(c)
		{
		case 'i':
		case 'I':
			Tree.input();
			break;
		case 'e':
		case 'E':Tree.codeprin();
			break;
		case 'd':
		case 'D':Tree.Decoding();
			break;
		case 'p':
		case 'P':
			cout<<"若没有编码就用已存在的文件打印!"<<endl;
			Tree.Print();
			break;
		case 't':
		case 'T':Tree.Tree();
			break;
		default:exit(1);
		}
	}
	return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值