zoukankan      html  css  js  c++  java
  • 哈夫曼编码课程设计+最小优先对列建树。

    1. 问题描述
      利用赫夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。这要求在发送端通过一个编码系统对待传输数据预先编码,在接收端将传来的数据进行译码(复原)。对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。试为这样的信息收发站编写一个赫夫曼码的编/译码系统。
    2. 基本要求
      一个完整的系统应具有以下功能:
      (1) I:初始化(Initialization)。从终端读入字符集大小n,以及n个字符和n个权值,建立赫夫曼树,并将它存于文件hfmTree中。
      (2) E:编码(Encoding)。利用已建好的赫夫曼树(如不在内存,则从文件hfmTree中读入),对文件ToBeTran中的正文进行编码,然后将结果存入文件CodeFile中。
      (3) D:译码(Decoding)。利用已建好的赫夫曼树将文件CodeFile中的代码进行译码,结果存入文件Textfile中。
    #include<bits/stdc++.h>
    #include <fstream>
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <vector>
    #include <string>
    #include <queue>
    #include <stack>
    #include <algorithm>
    #define INF 0x7fffffff
    #define EPS 1e-12
    #define MOD 1000000007
    #define PI 3.141592653579798
    #define N 100000
    using namespace std;
    typedef long long LL;
    const int maxn=1e5+7;
    map<char,string> kt;//保存字符与编码的对应关系
    struct htnode
    {
        int wei;
        char c;
        htnode *parent,*lch,*rch;
        htnode(char a='.',int b=0):c(a),wei(b)//构造函数
        {
            parent=lch=rch=NULL;
        }
    };
    struct cmp
    {
        bool operator()(htnode const *a,htnode const *b)
        {
            return a->wei>b->wei;
        }
    };//按照结构体的权值排序
    htnode* hufuman(htnode q[],int n)//用最小优先队列建哈夫曼树
    {
        priority_queue<htnode*,vector<htnode*>,cmp>st;//最小优先队列
        for(int i=0;i<n;i++)
        {
            st.push(&q[i]);
        }
        while(st.size()>1)
        {
            htnode *x,*y;
            x=st.top();
            st.pop();
            y=st.top();
            st.pop();
            htnode* z=new htnode('0',x->wei+y->wei);
            z->lch=x;z->rch=y;
            x->parent=y->parent=z;
            st.push(z);
            if(st.size()==1)break;
        }//每次选出两个最小的节点组成新的节点放入队列中
        return st.top();
    }
    void dfs(htnode* v,string s)//一次遍历得到哈夫曼编码保存在容器kt中左1
    {
        if(v->lch==NULL&&v->lch==NULL)
        {
            kt[v->c]=s;return;
        }
        string ss=s;
        ss+='1';//左儿子边为1
        dfs(v->lch,ss);
        ss=s;ss+='0';//右为儿子边为0
        dfs(v->rch,ss);
    }
    string zhuanyi(char s[])//把输入的字符文本转译为哈夫曼编码
    {
        int len=strlen(s);
       // cout<<len<<endl;
        string ans="";
        for(int i=0;i<len;i++)
        {
            ans+=kt[s[i]];
        }
        FILE *fp;
        fp=fopen("CodeFile.txt","w");
        for(int i=0;i<ans.size();i++)
        {
            fprintf(fp,"%c",ans[i]);//把转译之后的哈夫曼码写入文件中
        }
        if(fclose(fp))
        {
            printf("关闭文件失败
    ");
            exit(0);
        }
        return ans;
    }
    void get_c(htnode* v,string s,int &i,string &ans)//根据哈夫曼树找到对应字符
    {
        if(v->lch==NULL&&v->rch==NULL)
        {
            ans+=v->c;
            return ;
        }
        if(s[i]=='1')
        {
            get_c(v->lch,s,++i,ans);
        }
        else
        {
            get_c(v->rch,s,++i,ans);
        }
    }
    void Decoding(htnode *root)//从文本中读入哈夫曼编码并转译成文本
    {
        string tmp="",ans="";char ch;
        FILE *fp1,*fp2;
        if((fp1=fopen("CodeFile.txt","r"))==NULL)
        {
            printf("打开文件失败
    ");
            exit(0);
        }
        while(!feof(fp1))
        {
            ch=fgetc(fp1);//读入哈夫曼编码
            tmp+=ch;
        }
        if(fclose(fp1))
        {
            printf("关闭文件失败
    ");
            exit(0);
        }
        int i=0;
        while(i<tmp.size())
        {
            get_c(root,tmp,i,ans);//转译字符
        }
        cout<<ans<<endl;
        fp2=fopen("Textfile.txt","w");
        for(int i=0;i<ans.size()-1;i++)
        {
            fprintf(fp2,"%c",ans[i]);//转译之后的文本写入文件
        }
        for(int i=0;i<ans.size()-1;i++)
        {
            cout<<ans[i];
        }
        cout<<endl;
        if(fclose(fp2))
        {
            printf("关闭文件失败
    ");
            exit(0);
        }
    }
    void ddfs(htnode* v,FILE* fp)//遍历哈夫曼树来得到权值和左右儿子
    {
        if(v->lch==NULL&&v->rch==NULL)
        {
            cout<<v->c<<" "<<v->wei<<endl;
            fprintf(fp,"%c		%d
    ",v->c,v->wei);
            return ;
        }
        htnode *t,*tt;
        t=v->lch;tt=v->rch;
        cout<<v->c<<"		"<<v->wei<<"		"<<t->wei<<"		"<<tt->wei<<endl;
        fprintf(fp,"%c		%d		%d		%d",v->c,v->wei,t->wei,tt->wei);
        ddfs(v->lch,fp);
        ddfs(v->rch,fp);
    }
    void puts(htnode* root)//打印哈夫曼树并保存到文本中
    {
        FILE* fp;
        fp=fopen("hfm.txt","w");
        cout<<"哈夫曼树"<<endl;
        cout<<"字符		权值		左儿子权值		右儿子权值"<<endl;
        ddfs(root,fp);
        if(fclose(fp))
        {
            printf("关闭失败
    ");
            exit(0);
        }
    }
    int main()
    {
        int op,n;htnode *root;
            cout<<"请输入字符个数"<<endl;
            cin>>n;
            htnode *ht=new htnode[n];
            cout<<"请输入字符以及其所对应的次数"<<endl;
            for(int i=0;i<n;i++)
            {
                getchar();
               scanf("%c %d",&ht[i].c,&ht[i].wei);
            }
            root=hufuman(ht,n);dfs(root,"");
        map<char,string>::iterator it=kt.begin();
        while(it!=kt.end())
        {
            cout<<it->first<<" "<<it->second<<endl;
            it++;
        }
        puts(root);
        cout<<"请输入你要转换的文章"<<endl;
        char s[1000];
        getchar();
        gets(s);
        cout<<zhuanyi(s)<<endl;
        Decoding(root);
    }
    

    下面是实验报告
    链接:https://pan.baidu.com/s/1o8ooop8 密码:bk75

  • 相关阅读:
    spring框架
    自己来到这个世界的天数
    迭代器
    String
    mybatis-plus条件参数
    Linux常用命令
    web.xml
    log4j.properties
    springmvc.xml
    applicationContext.xml
  • 原文地址:https://www.cnblogs.com/lhclqslove/p/8093325.html
Copyright © 2011-2022 走看看