老师要求的编码= =,好吧,那树打印的确实很丑...
首先是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;
}