哈夫曼编码译码器实验报告

时间:2024.3.23

实验报告

哈夫曼编码及译码 

班级:软件工程一班

学号:2220141524

姓名:孙正涛

1 问题描述

1.设计一个利用哈夫曼算法的编码和译码系统,重复地显示并处理以下项目,直到选择退出为止。

(1) 将权值数据存放在数据文件(文件名为data.txt,位于当前目录中);

(2) 分别采用动态和静态存储结构; 初始化:键盘输入字符集大小n、n个字符和n个权值,建立哈夫曼树;
(3) 编码:利用建好的哈夫曼树生成哈夫曼编码;输出编码;

设计要求:

(1) 符合课题要求,实现相应功能;

(2) 要求界面友好美观,操作方便易行;

(3) 注意程序的实用性、安全性。

2 需求分析

     编写此软件是为了实现一个利用哈夫曼算法的编码和译码系统。比如,再利用电报进行通讯时,需要将文字转换成由二进制的字符组成的字符串。比如需传送的电文为“A B A C C D A”假设将A,B,C,D分别编码为00、01、10、11.则上述电文遍为00010010101100,总长度为14位。但是在传送过程中,总希望长度能够尽可能的短,于是我们想采用长度不等的编码。但是这种编码必须遵循:任何一个字符的编码都不是另一个字符编码的前缀。

对此软件的要求:能够正确的使得对于输入的字符进行编码以及译码,并且是的在译码过程中不会出错,同时能够将编码以及译码的结果正确的存入文件当中。

3 概要设计

总体框图以及功能描述

4 详细设计

数据类型的定义

(1)哈夫曼树节点类型

    struct hufmtreenode{               //哈弗曼树结点数据类型

           char data;

           float weight;                 //结点权值

           int parent,lchild,rchild;       //父结点,左、右孩子结点

     };

(2)哈夫曼树类型

    struct hufmtree{                   //哈弗曼树数据类型

           hufmtreenode *node;         //结点数组(根据n的值动态分配)

           int n;                        //叶子结点数

};

(3)哈夫曼编码数据类型

   struct Codetype{                     //哈弗曼编码数据类型

          char *bits;                    //编码流数组,

          int start;//编码实际在编码流数组里的开始位置

}

5 测试分析

(1)打开源文件统计各字符及权值信息并存入data.txt文件中    

(2)将统计出的权值信息进行哈夫曼编码

(3)将编码内容存入CodeFile.txt文件中

(4)将CodeFile.txt文件中的内容译码

(5)成功译码把原字符信息存入DeCodeFile.txt文件中

(6)输入各字符及其权值

(7)将各字符的权值信息进行哈夫曼编码

(7)根据编码再进行译码工作

6 课程设计总结

课程设计是培养学生综合运用所学知识,发现,提出,分析和解决实际问题,锻炼实践能力的重要环节,是对学生实际工作能力的具体训练和考察过程.随着科学技术发展的日新日异,当今计算机应用在生活中可以说得是无处不在。因此作为二十一世纪的大学来说掌握计算机开发技术是十分重要的。

回顾起此次课程设计,至今我仍感慨颇多,的确,自从拿到题目到完成整个编程,从理论到实践,在整整一个星期的日子里,可以学到很多很多的的东西,同时不仅可以巩固了以前所学过的知识,而且学到了很多在书本上所没有学到过的知识。通过这次课程设计使我懂得了理论与实际相结合是很重要的,只有理论知识是远远不够的,只有把所学的理论知识与实践相结合起来,从理论中得出结论,才能真正为社会服务,从而提高自己的实际动手能力和独立思考的能力。在设计的过程中遇到问题,这毕竟独立做的,难免会遇到过各种各样的问题,同时在设计的过程中发现了自己的不足之处,对以前所学过的知识理解得不够深刻,掌握得不够牢固,比如说结构体……通过这次课程设计之后,一定把以前所学过的知识重新温故。

这次课程设计终于顺利完成了,在设计中遇到了很多编程问题,最后在谢老师的辛勤指导下,终于游逆而解。同时,在李玉蓉老师的《软件工程导论》课上我学得到很多实用的知识,在次我表示感谢!同时,对给过我帮助的所有同学和各位指导老师再次表示忠心的感谢!

附录(源程序清单)

#include <stdio.h>

#include <conio.h>

#include <stdlib.h>

#define MAXVAL 10000.0

struct hufmtreenode{//哈弗曼树结点数据类型

    char data;

    double weight;//结点权值

    int parent,lchild,rchild;//父结点,左、右孩子结点

};

struct hufmtree{//哈弗曼树数据类型

    hufmtreenode *node;//结点数组(根据n的值动态分配)

    int n;//叶子结点数

};

struct Codetype{//哈弗曼编码数据类型

    char *bits;//编码流数组,n为为哈夫曼树中叶子结点的数目,编码的长度不可能超过n

    int start;//编码实际在编码流数组里的开始位置

};

void SortHufmtree(hufmtree *tree){//将哈夫曼树n个叶子结点由大到小排序

    int i,j,k;

    hufmtreenode temp;

    if (tree==NULL)

       return;

    for (i=0;i<tree->n;i++)

    {

       k=i;

       for(j=i+1;j<tree->n;j++)

           if (tree->node[j].weight>tree->node[k].weight)

              k=j;

       if (k!=i)

       {

           temp=tree->node[i];

           tree->node[i]=tree->node[k];

           tree->node[k]=temp;

       }

    }

}

Codetype* HuffmanCode(hufmtree *tree){//哈弗曼编码的生成

    int i,j,p,k;

    Codetype *code;

    if (tree==NULL)

       return NULL;

    code=(Codetype*)malloc(tree->n*sizeof(Codetype));

    for (i=0;i<tree->n;i++)

    {

       printf("%c ",tree->node[i].data);//打印字符信息

       code[i].bits=(char*)malloc(tree->n*sizeof(char));

       code[i].start=tree->n-1;

       j=i;

       p=tree->node[i].parent;

       while(p!=-1){

           if (tree->node[p].lchild==j)

              code[i].bits[code[i].start]='0';

           else

              code[i].bits[code[i].start]='1';

           code[i].start--;

           j=p;

           p=tree->node[p].parent;        

       }

       for (k=code[i].start+1;k<tree->n;k++)//打印字符编码    

           printf("%c",code[i].bits[k]);  

       printf("\n");

    }

    return code;

}

hufmtree* BuildHuffmanTree(hufmtree *tree){//构建叶子结点已初始化的哈夫曼树

    //tree中所有叶子结点已初始化

    int i,j,p1,p2,m;

    float small1,small2;

    m=2*(tree->n)-1; 

    for (i=tree->n;i<m;i++)//初始化所有非叶子结点

    {

       tree->node[i].parent=-1;

       tree->node[i].lchild=-1;

       tree->node[i].rchild=-1;

       tree->node[i].weight=0.0;

    }  

    for (i=tree->n;i<m;i++)//构建哈夫曼树

    {

       small1=small2=MAXVAL;

       for (j=0;j<=i-1;j++)

       {                       

           if (tree->node[j].parent==-1 && tree->node[j].weight<=small1)

           {                

              small1=tree->node[j].weight;                 

              p1=j;

           }

       }

       for (j=0;j<=i-1;j++)

        {         

           if (tree->node[j].parent==-1 && tree->node[j].weight<=small2 && (j!=p1))

           {

              small2=tree->node[j].weight;

              p2=j;

           }            

       }

       tree->node[p1].parent=tree->node[p2].parent=i;

       tree->node[i].weight=tree->node[p1].weight+tree->node[p2].weight;

       tree->node[i].lchild=p1;

       tree->node[i].rchild=p2;

    }

    return tree;

}

hufmtree* CreateHuffmanTreeFromSourceFile(){//通过解析源文件建立哈夫曼树

    FILE *textfile,*datafile;

    char ch,sourcefilename[100];

    int i,j=0,n=0;

    float count[128];                //用于统计字符在源文件中出现的次数,27表示26个英文字母和1个空格字符

    hufmtree *tree;

    //打开一个源文件

    printf("\n请输入源文件所在路径:\n");

    scanf("%s",sourcefilename);

   

    if ((textfile=fopen(sourcefilename,"r"))==NULL){

       printf("\n找不到文件%s\n",sourcefilename);

       return NULL;

    }

    for(i=0;i<128;i++)

       count[i]=0;

    //对源文件中各字符的个数统计

    ch=fgetc(textfile);

    while(!feof(textfile)){

       for(i=0;i<128;i++)

           if (ch==char(i)){

              count[i]++;

              break;

           }

       ch=fgetc(textfile);

    }  

    //将统计结果写入权值信息文件data.txt中,并构建哈夫曼树

    datafile=fopen("f:\\data.txt","w");

    for (i=0;i<128;i++)

       if (count[i]!=0)

           n++;  

    fprintf(datafile,"%d\n",n);

    tree=(hufmtree*)malloc(sizeof(hufmtree));

    tree->node=(hufmtreenode*)malloc((2*n-1)*sizeof(hufmtreenode));

    tree->n=n;

   

    printf("\n源文件的字符集及其权值信息如下:\n");

    for(i=0;i<128;i++)

       if (count[i]!=0)

       {

           //fprintf(datafile,"%c%f\n",char(i),count[i]);  

           fprintf(datafile,"%c  %.0f\n",char(i),count[i]);        

           printf("%c %.0f\n",char(i),count[i]);

           tree->node[j].data=char(i);

           tree->node[j].weight=count[i];

           tree->node[j].parent=-1;

           tree->node[j].lchild=-1;

           tree->node[j].rchild=-1;

           j++;

       }

    SortHufmtree(tree);

    BuildHuffmanTree(tree);

    fclose(textfile);

    fclose(datafile);

    printf("\n哈夫曼树建立完毕,已将权值信息保存至data.txt\n");

    return tree;

}

hufmtree* CreateHuffmanTreeByInput(){//通过用户输入建立哈夫曼树

    int n;

    hufmtree *tree;

    int i,m;

    FILE *datafile;

    tree=(hufmtree*)malloc(sizeof(hufmtree));

    datafile=fopen("f:\\data.txt","w");

    //由用户输入字符与权值信息并将其写入data.txt,同时进行哈夫曼树初始化

    printf("请输入字符数:");

    scanf("%d",&n);

    if (n<=0)

    {

       printf("\n您的输入有误。\n");

       return NULL;

    }

    tree->node=(hufmtreenode*)malloc((2*n-1)*sizeof(hufmtreenode));

    tree->n=n;

    m=2*n-1;

    for (i=0;i<n;i++)

    {

       tree->node[i].parent=-1;

       tree->node[i].lchild=-1;

       tree->node[i].rchild=-1;

       tree->node[i].weight=0.0;

    }

    fprintf(datafile,"%d\n",n);

    for (i=0;i<n;i++)

    {

       printf("\n输入第%d个字符及其权值:",i+1);

       tree->node[i].data=getche();

       tree->node[i].weight=getche();

       fprintf(datafile,"%c,%.0f\n",tree->node[i].data,tree->node[i].weight-48);

    }

    fclose(datafile);

    //哈夫曼树构建

    SortHufmtree(tree);

    BuildHuffmanTree(tree);

    printf("\n哈夫曼树建立完毕,已将权值信息保存至data.txt\n");

    return tree;

}

hufmtree* CreateHuffmanTreeFromDataFile(){//通过读取权值信息文件建立哈夫曼树

    FILE *datafile;

    int i,n;

    hufmtree *tree;

    if ((datafile=fopen("f:\\data.txt","r"))==NULL){

       printf("\n哈夫曼树尚未建立\n");

       return NULL;

    }

    //哈夫曼树初始化

    fscanf(datafile,"%d",&n);

    fgetc(datafile);

    tree=(hufmtree*)malloc(sizeof(hufmtree));

    tree->node=(hufmtreenode*)malloc((2*n-1)*sizeof(hufmtreenode));

    tree->n=n;

    for (i=0;i<n;i++){

       tree->node[i].data=fgetc(datafile);

       fscanf(datafile,"%f\n",&tree->node[i].weight);

       tree->node[i].parent=-1;

       tree->node[i].lchild=-1;

       tree->node[i].rchild=-1;

    }

    fclose(datafile);

    //哈夫曼树构建

    SortHufmtree(tree);

    BuildHuffmanTree(tree); 

    return tree;

}

hufmtree* Encoding(hufmtree *tree){//对源文件进行编码并将其输出至新文件

    FILE *textfile,*codefile;

    char ch,sourcefilename[50];

    int i,j;

    Codetype *code;

   

    if (tree==NULL)//如果内存中尚未建立哈夫曼树

    {//试从data.txt中读取权值信息并建立哈夫曼树

       tree=CreateHuffmanTreeFromDataFile();

       if (tree==NULL)

           return NULL;

    }

    //读取源文件

    printf("\n请输入源文件所在路径:\n");

    scanf("%s",sourcefilename);

    if ((textfile=fopen(sourcefilename,"r"))==NULL){

       printf("\n找不到文件%s\n",sourcefilename);

       return NULL;

    }

   

    //打印源文件内容

    printf("\n源文件的原文如下:\n");

    ch=fgetc(textfile);

    while(!feof(textfile)){

       printf("%c",ch);

       ch=fgetc(textfile);

    }     

   

    //编码

    printf("\n字符集的哈夫曼编码如下:\n");

    code=HuffmanCode(tree);

    //将源文件中各字符编码并写入codefile

    codefile=fopen("f:\\CodeFile.txt","w");

    fseek(textfile,0,SEEK_SET);

    ch=fgetc(textfile);

    while (!feof(textfile))

    {     

       for(i=0;i<tree->n;i++)

           if (ch==tree->node[i].data){

              for(j=code[i].start+1;j<tree->n;j++)

                  fputc(code[i].bits[j],codefile);  

              break;

           }

       if (i==tree->n)//在哈夫曼树树中找不到与文本内容里对应的字符

       {

           printf("\n字符%c不在哈夫曼树中,不能正确编码。\n",ch);

           fclose(codefile);

           return NULL;

       }

       ch=fgetc(textfile);

    }

    fclose(codefile);

    //提示成功信息并打印代码

    printf("\n编码成功,已将代码写入CodeFile.txt,代码如下:\n");

    codefile=fopen("f:\\CodeFile.txt","r");

    ch=fgetc(codefile);

    while(!feof(codefile)){

       printf("%c",ch);

       ch=fgetc(codefile); 

    }

    printf("\n");

    fclose(textfile);

    fclose(codefile);

    return tree;

}

void Decoding(hufmtree *tree)//对编码文件进行译码并将其输出至新文件

{

    FILE *codefile,*decodefile;

    char ch,codefilename[100];

    int i;

    if (tree==NULL)//如果尚未建立哈夫曼树

    {//试从data.txt中读取权值信息并建立哈夫曼树

       tree=CreateHuffmanTreeFromDataFile();

       if (tree==NULL)

           return ;

    }

    //打开编码文件

    printf("\n请输入代码文件所在路径:\n");

    scanf("%s",codefilename);

    if ((codefile=fopen(codefilename,"r"))==NULL){

       printf("\n找不到文件%s\n",codefilename);

       return;

    }

    //打印编码文件的正文

    printf("\n代码文件原文如下:\n");

    ch=fgetc(codefile);

    while(!feof(codefile)){

       printf("%c",ch);

       ch=fgetc(codefile); 

    }

    //进行译码并将译文写入DecodeFile

    decodefile=fopen("f:\\DecodeFile.txt","w");

    fseek(codefile,0,SEEK_SET);

    ch=fgetc(codefile);

    while(!feof(codefile))

    {

       for(i=2*tree->n-2;tree->node[i].lchild>=0 && tree->node[i].rchild>=0 && ch!=EOF;)

       {

           if(ch=='0')

              i = tree->node[i].lchild;

           else if(ch=='1')

              i = tree->node[i].rchild;

           else{

                  //printf("\n存在异常字符%c,不能正确译码。\n",ch);

                  return ;

           }

           if (i==-1)//在哈夫曼树中找不到对应叶子结点

           {

              printf("\n编码与当前哈夫曼树结构不相符,不能正确译码。\n",ch);

              fclose(decodefile);

              return;

           }

           ch=fgetc(codefile);

       }

       if (tree->node[i].lchild>=0 && tree->node[i].rchild>=0)

       {//寻找叶子结点的过程中突然读到了文件尾

           printf("\n代码文件编码内容不完整,不能完整译码。\n",ch);

           fclose(decodefile);

           return;

       }

       fputc(tree->node[i].data,decodefile);

    }

    fclose(decodefile);

    //提示成功信息并打印译文

    printf("\n\n译码成功,译文已保存至DecodeFile.txt\n");

    printf("译文如下:\n");

    decodefile=fopen("f:\\DecodeFile.txt","r");

    ch=fgetc(decodefile);

    while(!feof(decodefile)){

       printf("%c",ch);

       ch=fgetc(decodefile);   

    }

    printf("\n");

    fclose(codefile);

    fclose(decodefile);

}

void main(){

    hufmtree *tree=NULL;

    char choice;

    do

    {

       system("cls");

       printf("------------------\n");

       printf("     欢迎进入\n");

       printf("哈夫曼编码译码系统\n");

       printf("-*-*-*-*-*-*-*-*-*\n");

       printf("(1)---读取解析源文件建立哈夫曼树\n");

       printf("(2)---手动输入建立哈夫曼树\n");

       printf("(3)---打印字符集的哈夫曼编码\n");

       printf("(4)---对文本文件编码\n");

       printf("(5)---对代码文件译码\n");

       printf("(0)---退出系统\n");

       printf("-*-*-*-*-*-*-*-*-*\n");

       printf("请输入您的选择[0-5]:");

       choice=getche();

       printf("\n");

       switch (choice)

       {

       case '1':

           tree=CreateHuffmanTreeFromSourceFile();

           break;

       case '2':

           tree=CreateHuffmanTreeByInput();

           break;

       case '3':

           if (tree==NULL)

              tree=CreateHuffmanTreeFromDataFile();

           HuffmanCode(tree);

           break;

       case '4':

           tree=Encoding(tree);

           break;

       case '5':

           Decoding(tree);

           break;

       case '0':

           exit(0);

           break;

       default:printf("无效的选项。\n");

       }

       printf("\n");

       system("pause");

    }while (choice!='0');

}

更多相关推荐:
哈夫曼编码实验报告

哈夫曼编码器实验报告学院:计算机学院班级:计科0801班姓名:***学号:***一.实验目的练习树和哈夫曼树的有关操作,和各个算法程序,理解哈夫曼树的编码和译码二.实验环境Microsoftvisualc++三…

C语言-哈夫曼编码实验报告

福建工程学院课程设计课程数据结构题目哈夫曼编码和译码专业信息管理信息系统班级座号15号姓名林左权20xx年6月27日1实验题目哈夫曼编码和译码一要解决的问题利用哈夫曼编码进行信息通信可以大大提高信道利用率缩短信...

哈夫曼编码实验报告

数据结构作业报告哈夫曼编码实验报告姓名班级学号摘要本程序能执行让一段字符以哈夫曼编码的形式被转存或将一段哈夫曼编码翻译成字符通过字符的频率统计哈夫曼树的建立递归求字符的哈夫曼编码完成这个程序让我熟悉哈夫曼编码的...

哈夫曼编码实验报告

中南大学数据结构课程姓名刘阳班级信息0703学号0903070312实验时间081114指导老师赵颖

哈夫曼编码实验报告

北京邮电大学信息与通信工程学院数据结构实验报告实验名称实验三哈夫曼编码学生姓名牛佳宁班级20xx211107班内序号27学号10210213日期20xx年12月10日1实验要求利用二叉树结构实现赫夫曼编解码器1...

数据结构+哈夫曼编码+实验报告

实验报告一实验目的掌握哈夫曼树及其应用二实验内容利用哈夫曼算法构造最优二叉树然后对构造好的二叉树的叶子结点进行前缀编码三实验步骤1审清题意分析并理出解决问题的基本思路2根据基本思路设计好程序的算法3根据算法编写...

哈夫曼编码实验报告

数据结构实验班级软件C092姓名孙琼芳学号098586一实验目的利用哈夫曼编码进行通信可以大大提高信道利用率缩短信息传输时间降低传输成本但是这要求在发送端通过一个编码系统对待传数据预先编码在接收端将传来的数据进...

哈夫曼编译码实验指导书

实验七哈夫曼编/译码器一、实验目的通过哈夫曼树的构造,深刻理解二叉树的构造。通过哈夫曼编/译码过程,深刻领会二叉树的基本操作和二叉树的应用,帮助学生熟练掌握二叉数组织数据的基本原理和对二叉数操作的实现方法。二、…

数据结构实验二哈夫曼树及哈夫曼编码译码的实现

福建农林大学金山学院实验报告系教研室专业计算机科学与技术年级08实验课程姓名学号实验室号计算机号实验时间指导教师签字成绩实验二哈夫曼树及哈夫曼编码译码的实现验证性4学时一实验目的和要求构建哈夫曼树及哈夫曼编码输...

计算机算法设计与分析 哈夫曼编码 实验报告

学院实验报告纸计算机科学与工程学院院系网络工程专业071班组计算机算法设计与分析课哈夫曼编码问题1实验目的根据最优二叉树构造哈夫曼编码利用哈夫曼树很容易求出给定字符集及其概率分布的最优前缀码哈夫曼编码正是一种应...

哈夫曼编码 译码器 实验报告

数据结构课程设计报告QFileInfohufFileInfoHuffView负责具体画图classHuffViewpublicQGraphicsViewQOBJECTpublicexplicitHuffView...

哈夫曼编码课程设计报告

数据结构课程设计报告基于哈夫曼树的文件压缩解压程序专业班级信科2班姓名徐爱娟谢静学号20xx161431005120xx161431005020xx1231一需求分析1课题要求实现文件的压缩与解压并计算压缩率A...

哈夫曼编码实验报告(37篇)