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

时间:2024.4.7

数据结构与算法》课程设计

2009/2010学年第二学期第20周)

指导教师:王老师

班级:计算机科学与技术(3)班

学号:

姓名:


 

《数据结构与算法》课程设计

目    录

一、      前言

1.摘要

2.《数据结构与算法》课程设计任务书

二、实验目的

三、题目--赫夫曼编码/译码器

1.问题描述

2.基本要求

3.测试要求

4.实现提示

四、  需求分析--具体要求

五、  概要设计

六、  程序说明

七、  详细设计

八、  实验心得与体会


前言

1.摘要

     随着计算机的普遍应用与日益发展,其应用早已不局限于简单的数值运算,而涉及到问题的分析、数据结构框架的设计以及设计最短路线等复杂的非数值处理和操作。算法与数据结构的学习就是为以后利用计算机资源高效地开发非数值处理的计算机程序打下坚实的理论、方法和技术基础。

    算法与数据结构旨在分析研究计算机加工的数据对象的特性,以便选择适当的数据结构和存储结构,从而使建立在其上的解决问题的算法达到最优。

    数据结构是在整个计算机科学与技术领域上广泛被使用的术语。它用来反映一个数据的内部构成,即一个数据由那些成分数据构成,以什么方式构成,呈什么结构。数据结构有逻辑上的数据结构和物理上的数据结构之分。逻辑上的数据结构反映成分数据之间的逻辑关系,而物理上的数据结构反映成分数据在计算机内部的存储安排。数据结构是数据存在的形式。

《数据结构》主要介绍一些最常用的数据结构,阐明各种数据结构内在的逻辑关系,讨论其在计算机中的存储表示,以及在其上进行各种运算时的实现算法,并对算法的效率进行简单的分析和讨论。数据结构是介于数学、计算机软件和计算机硬件之间的一门计算机专业的核心课程,它是计算机程序设计、数据库、操作系统、编译原理及人工智能等的重要基础,广泛的应用于信息学、系统工程等各种领域。

    学习数据结构是为了将实际问题中所涉及的对象在计算机中表示出来并对它们进行处理。通过课程设计可以提高学生的思维能力,促进学生的综合应用能力和专业素质的提高。

 

2.《数据结构与算法》课程设计任务书

《数据结构与算法》是计算机专业重要的核心课程之一,在计算机专业的学习过程中占有非常重要的地位。《数据结构与算法课程设计》就是要运用本课程以及到目前为止的有关课程中的知识和技术来解决实际问题。特别是面临非数值计算类型的应用问题时,需要选择适当的数据结构,设计出满足一定时间和空间限制的有效算法。

本课程设计要求同学独立完成一个较为完整的应用需求分析。并在设计和编写具有一定规模程序的过程中,深化对《数据结构与算法》课程中基本概念、理论和方法的理解;训练综合运用所学知识处理实际问题的能力,强化面向对象的程序设计理念;使自己的程序设计与调试水平有一个明显的提高。

二、实验目的

    数据结构作为一门学科主要研究数据的各种逻辑结构和存储结构,以及对数据的各种操作。因此,主要有三个方面的内容:数据的逻辑结构;数据的物理存储结构;对数据的操作(或算法)。通常,算法的设计取决于数据的逻辑结构,算法的实现取决于数据的物理存储结构。数据结构是信息的一种组织方式,其目的是为了提高算法的效率,它通常与一组算法的集合相对应,通过这组算法集合可以对数据结构中的数据进行某种操作。

    在当今信息时代,信息技术己成为当代知识经济的核心技术。我们时刻都在和数据打交道。比如人们在外出工作时找最短路径,在银行查询存款、通过互联网查新闻、以及远程教育报名等,所有这些都在与数据发生关系。实际上,现实世界中的实体经过抽象以后,就可以成为计算机上所处理的数据。

    数据结构课程主要是研究非数值计算的程序设计问题中所出现的计算机操作对象以及它们之间的关系和操作的学科。数据结构是介于数学、计算机软件和计算机硬件之间的一门计算机专业的核心课程,它是计算机程序设计、数据库、操作系统、编译原理及人工智能等的重要基础,广泛的应用于信息学、系统工程等各种领域。

    学习数据结构是为了将实际问题中所涉及的对象在计算机中表示出来并对它们进行处理。通过课程设计可以提高学生的思维能力,促进学生的综合应用能力和专业素质的提高。通过此次课程设计主要达到以下目的:

¨                了解并掌握数据结构与算法的设计方法,具备初步的独立分析和设计能力;

¨ 初步掌握软件开发过程的问题分析、系统设计、程序编码、测试等基本方法和技能;

¨ 提高综合运用所学的理论知识和方法独立分析和解决问题的能力;

¨               训练用系统的观点和软件开发一般规范进行软件开发,培养软件工作者所应具备的科学的工作方法和作风。

三、题目--赫夫曼编码/译码器

1. 问题描述

利用赫夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。这要求在发送端通过一个编码系统对待传输数据预先编码,在接收端将传来的数据进行译码(复原)。对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。试为这样的信息收发站编写一个赫夫曼码的编/译码系统。

2.       基本要求

一个完整的系统应具有以下功能:

(1) I:初始化(Initialization)。从终端读入字符集大小n,以及n个字符和n个权值,建立赫夫曼树,并将它存于文件hfmTree中。

(2) E:编码(Encoding)。利用已建好的赫夫曼树(如不在内存,则从文件hfmTree中读入),对文件ToBeTran中的正文进行编码,然后将结果存入文件CodeFile中。

(3) D:译码(Decoding)。利用已建好的赫夫曼树将文件CodeFile中的代码进行译码,结果存入文件Textfile中。

以下为选做:

(4) P:印代码文件(Print)。将文件CodeFile以紧凑格式显示在终端上,每行50个代码。同时将此字符形式的编码文件写入文件CodePrin中。

(5) T:印赫夫曼树(Tree  printing)。将已在内存中的赫夫曼树以直观的方式(比如树)显示在终端上,同时将此字符形式的赫夫曼树写入文件TreePrint 中。

3.       测试要求

(1) 已知某系统在通信联络中只可能出现八种字符,其频率分别为0.05,0.29,0.07,0.08,0.14,0.23,0.03,0.11,试设计赫夫曼编码。

(2) 用下表给出的字符集和频度的实际统计数据建立赫夫曼树,并实现以下报文的编码和译码:“THIS PROGRAME  IS  MY  FAVORITE”。

4.       实现提示

(1) 编码结果以文本方式存储在文件Codefile中。

(2) 用户界面可以设计为“菜单”方式:显示上述功能符号,再加上“Q”,表示退出运行Quit。请用户键入一个选择功能符。此功能执行完毕后再显示此菜单,直至某次用户选择了“Q”为止。

(3) 在程序的一次执行过程中,第一次执行I,D或C命令之后,赫夫曼树已经在内存了,不必再读入。每次执行中不一定执行I命令,因为文件hfmTree可能早已建好。

四、具体要求

课程设计成果的内容必须由以下四个部分组成,缺一不可。

(1) 上交源程序:学生按照实验题目的具体要求所开发的所有源程序(应该放到一个文件夹中);

(2) 上交程序的说明文件:(保存在.txt中)在说明文档中应该写明上交程序所在的目录,上交程序的主程序文件名,如果需要安装,要有程序的安装使用说明;

(3) 设计报告:(保存在word 文档中,文件名要求: 按照“姓名_学号_设计题目”起名,如文件名为“ 张三_XXX_赫夫曼编码 ”.doc。打印稿用A4纸)。

其中包括:

¨         题目;

¨         实验目的;

¨         需求分析:在该部分中叙述实现的功能要求;

¨         概要设计:

在此说明每个部分的算法设计说明(可以是描述算法的流程图),每个程序中使用的存储结构设计说明(如果指定存储结构请写出该存储结构的定义);

¨         详细设计

各个算法实现的源程序,对每个题目要有相应的源程序(可以是一组源程序,每个功能模块采用不同的函数实现)。源程序要按照写程序的规则来编写。要结构清晰,重点函数的重点变量、重点功能部分要加上清晰的程序注释;

¨         调试分析

测试数据,测试输出的结果,时间复杂度分析,和每个模块设计和调试时存在问题的思考(问题是哪些?问题如何解决?),算法的改进设想;

¨         总结:

总结可以包括 : 设计过程的收获、遇到问题及解决问题过程的思考、程序调试能力的思考、对数据结构这门课程的思考、在设计过程中对《数据结构》课程的认识等内容。

(4)考核成绩评定标准:

本课程设计的评价由三部分组成,包括程序演示(50%),课程设计报告(30%),回答教师提问(20%)。

1.程序演示:

Ø  优         功能完善,全部测试正确,并且能够对局部进行完善。

Ø  良         功能完善,但测试欠缺。

Ø  中         功能基本完善,但程序尚有部分错误。

Ø  及格  完成内存中赫夫曼编码/译码,但不涉及文件操作。

Ø  不及格    功能不完善,且程序错误较多,无法运行。

2.课程设计报告:

1.优          包括设计内容,设计思想,已经完成的任务及达到的目标,设计思路清晰、书写条理清楚,源程序结构合理、清晰,注释说明完整,有对本次课程设计的心得体会。

2.良          包括设计内容,设计思想,已经完成的任务及达到的目标,设计思路基本清晰、书写条理基本清楚,源程序结构合理、清晰,注释说明基本完整,有对本次课程设计的心得体会。

3.中          课程设计报告内容基本完整,思路较清晰,书写基本清楚,源程序结构尚可,有注释说明但不完整。

4.及格   课程设计报告内容基本完整,思路较差,书写尚清楚。

5.不及格 课程设计报告内容不完整,书写没有条理。

3.回答教师提问:

1.   优         能回答教师提出的所有问题,并完全正确,思路清晰

2.  良         基本能回答教师提出的所有问题,有些小错误

3.  中         基本能回答教师提出的问题,少数问题回答错误或不清楚

4.  及格  能回答教师提出的问题,但较多问题回答错误或不能回答

5.  不及格    基本不能回答教师提出的问题

四、概要设计

1)        问题分析哈夫曼树的定义

1.哈夫曼树节点的数据类型定义为:

typedef struct{           //赫夫曼树的结构体

           char ch;

           int weight;              //权值

           int parent,lchild,rchild;

}htnode,*hfmtree;

2)所实现的功能函数如下

1、void hfmcoding(hfmtree &HT,hfmcode &HC,int n)初始化哈夫曼树,处理InputHuffman(Huffman Hfm)函数得到的数据,按照哈夫曼规则建立2叉树。此函数块调用了Select()函数。

2、void Select(hfmtree &HT,int a,int *p1,int *p2)          //Select函数,选出HT树到a为止,权值最小且parent为0的2个节点

 2、 int main()

主函数: 利用已建好的哈夫曼树(如不在内存,则从文件hfmtree.txt中读入)

对文件中的正文进行编码,然后将结果存入文件codefile.txt中。如果正文中没有要编码的字符,则键盘读入并存储到ToBeTran文件中。读入ToBeTran中将要编码的内容,将编码好的哈夫曼编码存储到CodeFile中。

3、Encoding

编码功能:对输入字符进行编码

4、Decoding

译码功能: 利用已建好的哈夫曼树将文件codefile.txt中的代码进行译码,结果存入文件textfile.dat 中。

 Print() 打印功能函数:输出哈夫曼树,字符,权值,以及它对应的编码。

     5.主函数的简要说明,主函数主要设计的是一个分支语句,让用户挑选所实现的功能。

使用链树存储,然后分别调用统计频数函数,排序函数,建立哈夫曼函数,编码函数,译码函数来实现功能。

2)系统结构图(功能模块图)

五.程序说明

1).哈夫曼编码/译码器源代码

#include<iostream.h>

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

#include<fstream.h>

typedef struct{         //赫夫曼树的结构体

        char ch;

        int weight;              //权值

        int parent,lchild,rchild;

}htnode,*hfmtree;

typedef char **hfmcode;

void Select(hfmtree &HT,int a,int *p1,int *p2) //Select函数,选出HT树到a为止,权值最小且parent为0的2个节点

{

        int i,j,x,y;

        for(j=1;j<=a;++j){

                if(HT[j].parent==0){

                        x=j;

                        break;

                }

        }

        for(i=j+1;i<=a;++i){

                if(HT[i].weight<HT[x].weight&&HT[i].parent==0){

                        x=i;                  //选出最小的节点

                }

        }

        for(j=1;j<=a;++j)        {

                if(HT[j].parent==0&&x!=j)

                {

                        y=j;

                        break;

                }

        }

        for(i=j+1;i<=a;++i)

        {

                if(HT[i].weight<HT[y].weight&&HT[i].parent==0&&x!=i)

                {

                        y=i;                  //选出次小的节点

                }

        }

        if(x>y){

                *p1=y;

                *p2=x;

        }

        else

        {

                *p1=x;

                *p2=y;

        }

}

void hfmcoding(hfmtree &HT,hfmcode &HC,int n) //构建赫夫曼树HT,并求出n个字符的赫夫曼编码HC

{

        int i,start,c,f,m,w;

        int p1,p2;

        char *cd,z;

        if(n<=1){

                return;

        }

        m=2*n-1;

        HT=(hfmtree)malloc((m+1)*sizeof(htnode));

        for(i=1;i<=n;++i)            //初始化n个叶子结点

        {

                printf("请输入第%d字符信息和权值:",i);

                scanf("%c%d",&z,&w);

                while(getchar()!='\n')

                {

                        continue;

                }

                HT[i].ch=z;

                HT[i].weight=w;

                HT[i].parent=0;

                HT[i].lchild=0;

                HT[i].rchild=0;

        }

        for(;i<=m;++i)        //初始化其余的结点

        {

                HT[i].ch='0';

                HT[i].weight=0;

                HT[i].parent=0;

                HT[i].lchild=0;

                HT[i].rchild=0;

        }

        for(i=n+1;i<=m;++i)        //建立赫夫曼树

        {

                Select(HT,i-1,&p1,&p2);

                HT[p1].parent=i;HT[p2].parent=i;

                HT[i].lchild=p1;HT[i].rchild=p2;

                HT[i].weight=HT[p1].weight+HT[p2].weight;

        }

        HC=(hfmcode)malloc((n+1)*sizeof(char *));

        cd=(char *)malloc(n*sizeof(char));

        cd[n-1]='\0';

        for(i=1;i<=n;++i)              //给n个字符编码

        {

                start=n-1;

                for(c=i,f=HT[i].parent;f!=0;c=f,f=HT[f].parent)

                {

                        if(HT[f].lchild==c)

                        {

                                cd[--start]='0';

                        }

                        else

                        {

                                cd[--start]='1';

                        }

                }

               

                HC[i]=(char*)malloc((n-start)*sizeof(char));

                strcpy(HC[i],&cd[start]);

        }

        free(cd);

}

int main(){

        char code[100],h[100],hl[100];

        int n,i,j,k,l;

        ifstream input_file;    //文件输入输出流

        ofstream output_file;

        char choice,str[100];

        hfmtree HT;

        hfmcode HC;

        cout<<"\n";

        cout<<"          "<<"计算机(3)班"<<"    "<<"Q07620307"<<"    "<<"XXX\n";

        while(choice!='Q'&&choice!='q')                //当choice的值不为q且不为Q时循环

        {

                cout<<"       "<<"*************************赫夫曼编码/译码器*************************\n";

            cout<<"            "<<"I.Init"<<"        "<<"E.Encoding"<<"        "<<"D.Decoding"<<"        "<<"Q.Exit\n";

            cout<<"请输入您要操作的步骤:";

                cin>>choice;

            if(choice=='I'||choice=='i')              //初始化赫夫曼树

                {

                        cout<<"请输入字符个数:";

                        cin>>n;

                        hfmcoding(HT,HC,n);

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

                        {

                                cout<<HT[i].ch<<":"<<HC[i]<<endl;

                        }

                        output_file.open("hfmTree.txt");

                        if(!output_file){

                                cout<<"can't oen file!"<<endl;

                                return 1;

                        }

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

                        {

                                output_file<<"("<<HT[i].ch<<HC[i]<<")";

                        }

                        output_file.close();

                        cout<<"赫夫曼树已经创建完毕,并且已经放入hfmTree.txt文件中!"<<endl;

                }

            else if(choice=='E'||choice=='e')           //进行编码,并将字符放入ToBeTran.txt,码值放入CodeFile.txt中

                {

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

                        gets(str);

                        output_file.open("ToBeTran.txt");

                        if(!output_file)

                        {

                                cout<<"can't oen file!"<<endl;

                                return 1;

                        }

                        output_file<<str<<endl;

                        output_file.close();

                        output_file.open("CodeFile.txt");

                        if(!output_file){

                                cout<<"can't oen file!"<<endl;

                                return 1;

                        }

                        for(i=0;i<strlen(str);i++){

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

                                {

                                        if(HT[j].ch==str[i])

                                        {

                                                output_file<<HC[j];

                                                break;

                                        }

                                }

                        }

                        output_file.close();

                        cout<<"\n";

                        cout<<"编码完毕,并且已经存入CodeFile.txt文件!\n";

                        input_file.open("CodeFile.txt");         //从CodeFile.txt中读入编码,输出在终端

                        if(!input_file)

                        {

                                cout<<"can't oen file!"<<endl;

                                return 1;

                        }

                        input_file>>code;

                        cout<<"编码码值为:"<<code<<endl;

                        input_file.close();

                }

            else if(choice=='D'||choice=='d')     //读入CodeFile.txt中的编码进行译码,将译出来的字符放入Textfile.txt中

                {

                        input_file.open("CodeFile.txt");

                        if(!input_file){

                                cout<<"can't oen file!"<<endl;

                                return 1;

                        }

                        input_file>>h;

                        input_file.close();

                        output_file.open("Textfile.txt");

                        if(!output_file)

                       {

                                cout<<"can't oen file!"<<endl;

                                return 1;

                        }

                        k=0;

                        while(h[k]!='\0')           //先用编码中的前几个和字符的编码相比较,然后往后移

                        {

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

                                        l=k;

                                        for(j=0;j<strlen(HC[i]);j++,l++){

                                                hl[j]=h[l];

                                        }

                                        hl[j]='\0';

                                        if(strcmp(HC[i],hl)==0)

                                        {

                                                output_file<<HT[i].ch;

                                                k=k+strlen(HC[i]);

                                                break;

                                        }

                                }

                        }

                        output_file.close();

                        input_file.open("Textfile.txt");

                        if(!input_file){

                                cout<<"can't oen file!"<<endl;

                                return 1;

                        }

                        input_file>>h;

                        cout<<h<<endl;

                        input_file.close();

                        cout<<"译码结束,字符已经存入Textfile.txt文件中!"<<endl;

                }

            else if(choice=='Q'||choice=='q')            //退出程序

                {

                        exit(0);

                }

            else               //如果选了选项之外的就让用户重新选择

                {

                        cout<<"您没有输入正确的步骤,请重新输入!"<<endl;

                }

                cout<<endl;

        }

        return 0;

}

六.调试分析

编码

、译码

、退出

 

七.实验心得与体会

    在我自己课程设计中,就在编写好源代码后的调试中出现了不少的错误,遇到了很多麻烦及困难,我的调试及其中的错误和我最终找出错误,修改为正确的能够执行的程序中,通过分析,我学到了:

在定义头文件时可多不可少,即我们可多写些头文件,肯定不会出错,但是若没有定义所引用的相关头文件,必定调试不通过;

在执行译码操作时,不知什么原因,总是不能把要编译的二进制数与编译成的字符用连接号连接起来,而是按顺序直接放在一起,视觉效果不是很好。还有就是,很遗憾的是,我们的哈夫曼编码/译码器没有像老师要求的那样完成编一个文件的功能,这是我们设计的失败之处。

    通过本次数据结构的课程设计,我学习了很多在上课没懂的知识,并对求哈夫曼树及哈夫曼编码/译码的算法有了更加深刻的了解,更巩固了课堂中学习有关于哈夫曼编码的知识,真正学会一种算法了。当求解一个算法时,不是拿到问题就不加思索地做,而是首先要先对它有个大概的了解,接着再详细地分析每一步怎么做,无论自己以前是否有处理过相似的问题,只要按照以上的步骤,必定会顺利地做出来。

    这次课程设计,我在编辑中犯了不应有的错误,设计统计字符和合并时忘记应该怎样保存数据,对文件的操作也很生疏。在不断分析后明确并改正了错误和疏漏,我的程序有了更高的质量。


考核成绩评定表

签字:

            

更多相关推荐:
数据结构课程设计总结

课程设计说明书课程名:《数据结构课程设计》题目:一元多项式运算系统20##年1月一、课程认识数据结构课程主要是研究非数值计算的程序设计问题中所出现的计算机操作对象以及它们之间的关系和操作的学科。数据结构是介于数…

数据结构课程设计心得体会

程序设计心得体会做了一个星期的程序设计终于做完了,在这次程序设计课中,真是让我获益匪浅,我突然发现写程序还挺有意思的。由于上学期的C语言跟这学期的数据结构都算不上真正的懂,对于书上的稍微难点的知识就是是而非的,…

《数据结构课程设计报告》

安徽省巢湖学院计算机与信息工程学院课程设计报告课程名称课题名称用三元组实现稀疏矩阵的转置相加相乘专业计算机科学与技术班级学号AA姓名AAA联系方式136XXXXXXXX指导教师武彬20年月日目录1数据结构课程设...

数据结构课程设计总结

课程设计总结一周的课程设计结束了,在这次的课程设计中不仅检验了我所学习的知识,也培养了我如何去把握一件事情,如何去做一件事情,又如何完成一件事情的方法和技巧。在设计过程中,和同学们相互探讨,相互学习,相互监督。…

数据结构课程设计报告(含代码)

西安郵電學院数据结构课程设计报告题目校园导航系统院系名称计算机学院专业名称计算机科学与技术班级学生姓名学号8位指导教师设计起止时间20xx年12月11日20xx年12月15日一设计目的1通过本次课程设计巩固数据...

数据结构课程设计报告

CENTRALSOUTHUNIVERSITY数据结构课程设计报告题目学生姓名指导教师学院专业班级完成时间交通旅游图的最短路径问题摘要数据结构主要是一门研究非数值计算的程序设计问题中的计算机操作对象以及它们之间的...

数据结构课程设计总结 (1)

《程序设计与数据结构》综合课程设计论文题目:程序设计与数据结构综合课程设计专业:计算机科学与技术班级:N计科12-1F姓名:学号:指导老师:一、课程认识数据结构课程主要是研究非数值计算的程序设计问题中所出现的计…

数据结构课程设计报告-关键路径

数据结构课程设计报告学院计算机与通信工程专业网络工程班级学号学生姓名指导教师课程成绩完成日期20xx年2月27日数据结构程序设计学院计算机与通信工程学院专业网络工程班级学号学生姓名指导教师完成日期20xx年2月...

数据结构课程设计报告

淮阴工学院数据结构课程设计报告选题名称无向图应用问题系院计算机工程学院专业计算机科学与技术班级网络1111姓名1111311105指导教师周海岩单劲松学年学期20xx20xx学年第1学期年1设计任务书2摘要本课...

数据结构课程设计——报告(样例)

数据结构与算法课程设计报告王婧龚丹宋毅编写题目航空订票管理系统学期20xx秋班号学号姓名成绩哈尔滨华德学院电子与信息工程学院20xx年12月一实训设计的目的与要求注正文为宋体五号字为单倍行距一课程设计目的不少于...

厦门理工 数据结构课程设计报告2

《数据结构与算法》课程设计报告(20##20##学年第1学期)专业:网络工程班级:11网络工程姓名学号:指导教师:成绩:计算机科学与技术系目录一.课程设计目的与要求11.设计目的12.设计任务及要求1二.方案实…

迷宫求解数据结构课程设计报告

数据结构课程设计数据结构课程设计报告课题名称迷宫求解姓名马兆瑞学号20xx03021071专业电子信息科学与技术班级信息092班指导教师侯瑞莲数据结构课程设计目录第一部分引言3第二部分课程设计报告3第一章课程设...

数据结构课程设计总结(48篇)