哈夫曼树

#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;
        }
    }
}
posted @ 2019-12-17 20:09  ChildeZhe  阅读(230)  评论(0)    收藏  举报