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

  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

时间: 2024-10-11 16:10:32

哈夫曼编码课程设计+最小优先对列建树。的相关文章

数据结构课程设计-哈夫曼编码译码

//******************************************** //程序功能:哈夫曼编码及译码 // //日期:2014年11月18 // //******************************************** #include<stdio.h> #include<stdlib.h> #include<string.h> #include <windows.h> #define MAX 128 //叶子节点

哈夫曼编码(Huffman coding)的那些事,(编码技术介绍和程序实现)

前言 哈夫曼编码(Huffman coding)是一种可变长的前缀码.哈夫曼编码使用的算法是David A. Huffman还是在MIT的学生时提出的,并且在1952年发表了名为<A Method for the Construction of Minimum-Redundancy Codes>的文章.编码这种编码的过程叫做哈夫曼编码,它是一种普遍的熵编码技术,包括用于无损数据压缩领域.由于哈夫曼编码的运用广泛,本文将简要介绍: 哈夫曼编码的编码(不包含解码)原理 代码(java)实现过程 一

基于哈夫曼编码的压缩解压程序

这个程序是研一上学期的课程大作业.当时,跨专业的我只有一点 C 语言和数据结构基础,为此,我查阅了不少资料,再加上自己的思考和分析,实现后不断调试.测试和完善,耗时一周左右,在 2012/11/19 完成.虽然这是一个很小的程序,但却是我完成的第一个程序. 源码托管在 Github:点此打开链接 一.问题描述: 名称:基于哈夫曼编码的文件压缩解压 目的:利用哈夫曼编码压缩存储文件,节省空间 输入:任何格式的文件(压缩)或压缩文件(解压) 输出:压缩文件或解压后的原文件 功能:利用哈夫曼编码压缩解

基于python的二元霍夫曼编码译码详细设计

一.设计题目 对一幅BMP格式的灰度图像(个人证件照片)进行二元霍夫曼编码和译码 二.算法设计 (1)二元霍夫曼编码: ①:图像灰度处理: 利用python的PIL自带的灰度图像转换函数,首先将彩色图片转为灰度的bmp图像,此时每个像素点可以用单个像素点来表示. ②:二元霍夫曼编码: 程序流程图: 详细设计: 统计像素点频率,首先通过python自带的PIL库的图像像素点读取函数read()获取灰度图像的所有像素点,通过循环遍历每个像素点,将每个出现的像素点值以及其次数以键值对的形式放入到pyt

机智零崎不会没梗Ⅱ (哈夫曼编码、优先队列)

题目描述 你满心欢喜的召唤出了外星生物,以为可以变身超人拥有强大力量战胜一切怪兽,然而面对着身前高大的外星生物你一脸茫然,因为,你懂M78星云语吗?不过不用担心,因为零崎非常机智,他给出了关键性的提示:“讲道理,日语可是全宇宙通用语,所以为什么不试试和外星人讲日语呢?” 不过现在外星生物说的话都是“[email protected]#$%^&%#%I&!……”这样的东西,你要怎么转换成日语呢? 作位全宇宙通用的日语,自然有一套万能的转换算法,那就是Huffman编码转换!当然了这肯定不是普

数据压缩之经典——哈夫曼编码(Huffman)

(笔记图片截图自课程Image and video processing: From Mars to Hollywood with a stop at the hospital的教学视频,使用时请注意版权要求.) JPEG用哈夫曼编码(Huffman Encoder)作为其符号编码.哈弗曼编码是压缩算法中的经典,它理论上可以将数据编成平均长度最小的无前缀码(Prefix-Free Code). 为什么要进行编码? 关于Lena:莱娜图(Lenna)是指刊于1972年11月号<花花公子>(Pla

霍夫曼编码/译码器

赫夫曼树的应用 1.哈夫曼编码 在数据通信中,需要将传送的文字转换成二进制的字符串,用0,1码的不同排列来表示字符.例如,需传送的报文为"AFTER DATA EAR ARE ART AREA",这里用到的字符集为"A,E,R,T,F,D",各字母出现的次数为{8,4,5,3,1,1}.现要求为这些字母设计编码.要区别6个字母,最简单的二进制编码方式是等长编码,固定采用3位二进制,可分别用000.001.010.011.100.101对"A,E,R,T,F

哈夫曼编码问题

本博客的代码的思想和图片参考:好大学慕课浙江大学陈越老师.何钦铭老师的<数据结构> 哈夫曼编码问题 1 引子 1.1 将百分制的考试成绩转换成五分制的成绩,程序如下: if( score < 60 ) grade =1;else if( score < 70 ) grade =2;else if( score < 80 ) grade =3;else if( score < 90 ) grade =4;else grade =5; 那么上面这个其实是一棵判断树: 我们发

哈夫曼(Huffman)树与哈夫曼编码

声明:原创作品,转载时请注明文章来自SAP师太技术博客:www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将追究法律责任!原文链接:http://www.cnblogs.com/jiangzhengjun/p/4289610.html 哈夫曼树又称最优二叉树,是一种带权路径长最短的树.树的路径长度是从树根到每一个叶子之间的路径长度之和.节点的带树路径长度为从该节点到树根之间的路径长度与该节点权(比如字符在某串中的使用频率)的乘积. 比如有一串字符串如