#include<bits/stdc++.h>
#include<graphics.h>
using namespace std;
struct Node
{
int num;
int weight;
char c='0';
int parent=0,lchild=0,rchild=0;
string code;
bool operator<(const Node& tmp) const
{
if(this->weight<tmp.weight) return true;
else if(this->weight==tmp.weight)
{
return this->num<tmp.num;
}
else return false;
}
};
Print()
{
cout<<"------------------------"<<endl;
cout<<"1.建立哈夫曼树"<<endl;
cout<<"2.编码"<<endl;
cout<<"3.译码"<<endl;
cout<<"4.打印代码文件"<<endl;
cout<<"5.打印哈夫曼树"<<endl;
cout<<"0.退出"<<endl;
cout<<"------------------------"<<endl;
}
void CreateTree()
{
cout<<"请输入总共字符数:";
int n;cin>>n;
int tot=2*n-1;
Node node[tot+1];
for(int i=1;i<=tot;i++) node[i].num=i;
cout<<"请依次输入字符与其权值:"<<endl;
set<Node>s;set<Node>::iterator it;
cin.get();
for(int i=1;i<=n;i++)
{
Node a;
cin.get(node[i].c);
cin>>node[i].weight;
a=node[i];
s.insert(a);
if(i!=n) cin.get();
}
for(int i=n+1;i<=tot;i++)
{
int s1,s2;
it=s.begin();s1=it->num;s.erase(it);
it=s.begin();s2=it->num;s.erase(it);
node[s1].parent=i;node[s2].parent=i;
node[i].lchild=s1;node[i].rchild=s2;
node[i].weight=node[s1].weight+node[s2].weight;
Node a;a=node[i];
s.insert(a);
}
cout<<"请输入记录哈夫曼树的文件名:";
char filename[100];
cin>>filename;
ofstream fout(filename);
fout<<tot<<endl;
for(int i=1;i<=tot;i++)
{
fout<<node[i].c<<" "<<node[i].weight<<" "<<node[i].parent<<" "<<node[i].lchild<<" "<<node[i].rchild<<" "<<node[i].num<<endl;
}
}
void Encode()
{
cout<<"请输入编码哈夫曼树文件名:";
char filename[100];cin>>filename;
ifstream fin(filename);
int tot;
fin>>tot;
Node node[tot+1];
for(int i=1;i<=tot;i++)
{
fin.get();fin.get(node[i].c);
fin>>node[i].weight>>node[i].parent>>node[i].lchild>>node[i].rchild>>node[i].num;
}
int n=(tot+1)/2;
char code[n];
code[n-1]='\0';
for(int i=1;i<=n;i++)
{
int start=n-1;
for(int c=i,f=node[i].parent;f;c=f,f=node[f].parent)
{
if(node[f].lchild==c) code[--start]='0';
else code[--start]='1';
}
node[i].code=code+start;
}
string s,haffcode;
cout<<"请输入需要编码文件名:";
char encodename[100];cin>>encodename;
ifstream fiin(encodename);
getline(fiin,s);
for(int i=0;i<s.size();i++)
{
for(int j=1;j<=n;j++)
{
if(s[i]==node[j].c) {haffcode+=node[j].code;break;}
}
}
cout<<"请输入编码存放位置文件名:";
char outname[100];cin>>outname;
ofstream fout(outname);
fout<<haffcode;
}
void Decode()
{
string s;
cout<<"请输入需要译码的文件:";
char encodename[100];cin>>encodename;
ifstream filmin(encodename);
getline(filmin,s);
cout<<"请输入译码所用的哈夫曼树:";
char filename[100];cin>>filename;
ifstream fin(filename);
int tot;
fin>>tot;
Node node[tot+1];
for(int i=1;i<=tot;i++)
{
fin.get();fin.get(node[i].c);
fin>>node[i].weight>>node[i].parent>>node[i].lchild>>node[i].rchild>>node[i].num;
}
int n=(tot+1)/2;
int cnt=-1;
char finalcode[1000];
int now=tot;
for(int i=0;i<s.size();i++)
{
if(s[i]=='0') now=node[now].lchild;
else if(s[i]=='1') now=node[now].rchild;
if(node[now].c!='0') {finalcode[++cnt]=node[now].c;now=tot;}
}
cout<<"请输入译码存放位置文件名:";
char outname[100];cin>>outname;
ofstream fout(outname);
for(int i=0;i<cnt;i++) fout<<finalcode[i];
}
void PrintCode()
{
string s;
cout<<"请输入需要显示译码的文件:";
char encodename[100];cin>>encodename;
ifstream filmin(encodename);
filmin>>s;
for(int i=0;i<=s.size();i++)
{
cout<<s[i];
if((i+1)%50==0&&i!=0) cout<<endl;
}
cout<<endl;
}
int inorder[100000];int tott,cntt;Node nodee[100000];
void InOrder(int now)
{
if(nodee[now].lchild!=0) InOrder(nodee[now].lchild);
if(now!=0) inorder[++cntt]=nodee[now].num;
if(nodee[now].rchild!=0) InOrder(nodee[now].rchild);
}
int search_(int num)
{
for(int i=1;i<=tott;i++)
{
if(inorder[i]==num)
{
return i;
}
}
}
void PrintTree()
{
cout<<"请输入需要打印哈夫曼树文件名:";
char filename[100];cin>>filename;
ifstream fin(filename);
fin>>tott;int n=(tott+1)/2;
for(int i=1;i<=tott;i++)
{
fin.get();fin.get(nodee[i].c);
fin>>nodee[i].weight>>nodee[i].parent>>nodee[i].lchild>>nodee[i].rchild>>nodee[i].num;
}
InOrder(tott);
queue<int>q;q.push(tott);
cntt=0;initgraph(1500,700);
while(!q.empty())
{
cntt++;
vector<int>v;
while(!q.empty()) {v.push_back(q.front());q.pop();}
for(int i=0;i<v.size();i++)
{
circle(search_(nodee[v[i]].num)*15,cntt*30,10);
int father=nodee[v[i]].parent;
if(father) line(search_(nodee[father].num)*15,(cntt-1)*30,search_(nodee[v[i]].num)*15,cntt*30);
if(nodee[v[i]].lchild) q.push(nodee[v[i]].lchild);
if(nodee[v[i]].rchild) q.push(nodee[v[i]].rchild);
}
}
getch();
}
int main()
{
while(1)
{
Print();
int choice;cin>>choice;
switch(choice)
{
case 0:break;
case 1:CreateTree();break;
case 2:Encode();break;
case 3:Decode();break;
case 4:PrintCode();break;
case 5:PrintTree();break;
default:cout<<"无效输入!"<<endl;
}
}
}