哈夫曼编码课程设计+最小优先对列建树。

  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("关闭文件失败\n");
        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("打开文件失败\n");
        exit(0);
    }
    while(!feof(fp1))
    {
        ch=fgetc(fp1);//读入哈夫曼编码
        tmp+=ch;
    }
    if(fclose(fp1))
    {
        printf("关闭文件失败\n");
        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("关闭文件失败\n");
        exit(0);
    }
}
void ddfs(htnode* v,FILE* fp)//遍历哈夫曼树来得到权值和左右儿子
{
    if(v->lch==NULL&&v->rch==NULL)
    {
        cout<<v->c<<" "<<v->wei<<endl;
        fprintf(fp,"%c\t\t%d\n",v->c,v->wei);
        return ;
    }
    htnode *t,*tt;
    t=v->lch;tt=v->rch;
    cout<<v->c<<"\t\t"<<v->wei<<"\t\t"<<t->wei<<"\t\t"<<tt->wei<<endl;
    fprintf(fp,"%c\t\t%d\t\t%d\t\t%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<<"字符\t\t权值\t\t左儿子权值\t\t右儿子权值"<<endl;
    ddfs(root,fp);
    if(fclose(fp))
    {
        printf("关闭失败\n");
        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

posted @ 2017-12-23 14:09  lhclqslove  阅读(404)  评论(0编辑  收藏  举报