哈夫曼编码课程设计
哈夫曼编码译码器课程设计
哈夫曼编码译码器课程设计1.哈夫曼编码是一种有效的数据压缩算法,通过将最常用的字符编码为较短的比特串,最大限度地减少了存储空间。
本文档介绍一个哈夫曼编码译码器的设计和实现,该译码器可以实现从原始文本到哈夫曼编码的转换,并且可以从哈夫曼编码还原出原始文本。
2. 设计和实现本译码器的开发采用Python语言,主要分为两部分:哈夫曼编码和译码两部分。
2.1 哈夫曼编码哈夫曼编码的过程主要分为两步:1.统计每个字符出现的频率,并生成一个频率表。
2.根据频率表生成哈夫曼树,并生成相应的编码表。
以下是用于生成哈夫曼编码的Python代码:import heapqfrom collections import defaultdictclass Node:def__init__(self, freq, char=None, left=None, right=None): self.freq = freqself.char = charself.left = leftself.right = rightdef__lt__(self, other):return self.freq < other.freqdef__eq__(self, other):return self.freq == other.freqdef build_tree(data):freq = defaultdict(int)for char in data:freq[char] +=1q = [Node(freq[char], char) for char in freq]heapq.heapify(q)while len(q) >1:left = heapq.heappop(q)right = heapq.heappop(q)parent = Node(left.freq + right.freq, left.char + right.char, l eft, right)heapq.heappush(q, parent)return q[0]def generate_codes(node, current_code='', codes={}):if node is None:returnif node.char is not None:codes[node.char] = current_codegenerate_codes(node.left, current_code +'0', codes)generate_codes(node.right, current_code +'1', codes)return codes通过调用build_tree()函数来生成哈夫曼树,并调用generate_codes()函数来生成编码表。
数据结构课程设计 哈夫曼编码与译码器课程设计
数据结构课程设计题目名称:哈夫曼编码与译码器课程设计计算机科学与技术学院1.需求分析(1)熟练掌握哈夫曼编译原理(2)掌握程序设计步骤(3)根据哈夫曼编码原理,设计一个程序,在已知相关字符和字符对应权值(文件中存在或者用户输入)的情况下,根据用户要求对相应内容进行编码、译码等相应操作。
(4)输入的形式和输入值的范围;(5) 输出的形式;(6) 程序所能达到的功能;(7) 测试数据:包括正确的输入及其输出结果和含有错误的输入及其输出结果2.概要设计1.写好流程图,设计实验方案。
2.初始化,从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树,并将它存于文件HuofumanTree中。
3.编码。
利用已建好的哈夫曼树,对文件ToBeTran中的正文进行编码,然后将结果存入文件CodeFile中。
4.译码。
利用已建好的哈夫曼树将文件CodeFile中的代码进行译码,结果存入文件Textfile中。
5.印代码文件(Print)将文件CodeFile以紧凑格式显示在终端上,每行50个代码。
同时将此字符形式的编码文件写入文件CodePrint中。
6.印哈夫曼树(Treeprinting).将已在内存中的哈夫曼树以直观的方式(比如树)显示在终端上,同时将此字符形式的哈夫曼树写入文件TreePrint中。
具体函数如下:1.Initialization()初始化2.Encoding()编码3.Decoding()译码4.Print_file()打印代码文件5.search(k,j,p)搜索二叉树6.Print_tree() 打印二叉树7.menu()主菜单8.main()主函数3.详细设计(1)哈夫曼结点定义类型以一个节点为单位,其中节点中包括他的父亲·左孩子·右孩子,权值(2)存储字符信息(3)用于编码时存取字符长度及起始位置(4)初始化将数据存入文件中void Initialization(){int i,j;FILE* HFM_f;//定义一个指针指向文件HFM_f = fopen("C:/Users/lenovo/Desktop/x.txt","w");//将文件打开,赋值给HFM_fif(HFM_f == NULL){printf("create file error!\n");}printf(" 请输入字符集大小: ");scanf("%d",&leaves);fprintf(HFM_f,"----输入的值-----\n");fprintf(HFM_f," 字符大小%4d\n",leaves);fprintf(HFM_f," 字符权值\n");for(i=0; i<leaves; i++){printf(" 请输入第%d个字符和其权:",i+1);scanf(" %c ",&HFM_num[i].hfstr);scanf("%d",&HFM_num[i].weight);fprintf(HFM_f,"%4c",HFM_num[i].hfstr);fprintf(HFM_f,"%4d\n",HFM_num[i].weight); //存储字符和权值}(5)建立哈夫曼树for(i=0; i<maxsize; i++)//哈夫曼树初始化{HFM_tree[i].parent = -1;HFM_tree[i].lchild = -1;HFM_tree[i].rchild = -1;HFM_tree[i].weight = 0;}for(i=0; i<leaves; i++){HFM_tree[i].weight = HFM_num[i].weight;}for(i=0; i<leaves-1; i++){int m1,m2;int m1_pos,m2_pos;m1=m2=65536;m1_pos=m2_pos=0;for(j=0; j<leaves+i; j++)//选出最小且没被访问的两个数{if(HFM_tree[j].weight<m1&&HFM_tree[j].parent == -1) {m2 = m1;m1 = HFM_tree[j].weight;m2_pos = m1_pos;m1_pos = j;}else{if(HFM_tree[j].weight<m2&&HFM_tree[j].parent == -1){m2 = HFM_tree[j].weight;m2_pos = j;}}}HFM_tree[leaves+i].parent = -1;HFM_tree[leaves+i].lchild = m1_pos;//HFM_tree[leaves+i]为两者的最小和的结点,即他们的父亲HFM_tree[leaves+i].rchild = m2_pos;HFM_tree[m1_pos].parent = leaves+i;HFM_tree[m2_pos].parent = leaves+i;HFM_tree[leaves+i].weight = m2+m1;//将和赋为他们的父亲结点的权值}(6)输出哈夫曼树printf("----------------哈夫曼编码--------------\n");printf(" parent lchild rchild weight\n");fprintf(HFM_f,"-------------哈夫曼编码------------\n");fprintf(HFM_f," parent lchild rchild weight\n");for(i=0; i<leaves*2-1; i++){printf("%8d%8d%8d%8d\n",HFM_tree[i].parent,HFM_tree[i].lchild,HFM_tre e[i].rchild,HFM_tree[i].weight);fprintf(HFM_f,"%8d%8d%8d%8d\n",HFM_tree[i].parent,HFM_tree[i].lchild, HFM_tree[i].rchild,HFM_tree[i].weight);}printf("\n");fclose(HFM_f);//关上文件}(7)编码void Encoding(){int i,j,p,c,k;FILE* HFM_f = fopen("CodeFile.txt","w");//打开文件if(HFM_f == NULL){printf("open file error!\n");}for(i=0; i<leaves; i++){c = i;//当前结点编号p = HFM_tree[i].parent;//父亲结点编号HFM_hf.start = len-1;//单个结点路径长度-1,即循环次数,从0开始算while(p!=-1)//根节点的p=-1,即根结点的父亲值为-1,即为初始化的值,证明根节点没有父亲结点{if(HFM_tree[p].lchild == c)//若左孩子为C,赋值0{HFM_hf.bit[HFM_hf.start] = 0;}else{HFM_hf.bit[HFM_hf.start] = 1;//若右孩子为c,赋值1 }--HFM_hf.start;c = p;//沿着树往上走,将刚才的父亲变为孩子p = HFM_tree[c].parent;//寻找当前结点的父亲,即原节点的爷爷}for(j=HFM_hf.start+1,k=0; j<len; j++,k++){HFM_code[i].bit[k] = HFM_hf.bit[j];}HFM_code[i].length = len-HFM_hf.start-1;HFM_code[i].start = HFM_hf.start+1;}for(i=0; i<leaves; i++){HFM_code[i].hfch = HFM_num[i].hfstr;printf(" character:%c start:%d length:%dCode:",HFM_code[i].hfch,HFM_code[i].start,HFM_code[i].length );for(j=0; j<HFM_code[i].length; j++){printf("%d",HFM_code[i].bit[j]);fprintf(HFM_f,"%d",HFM_code[i].bit[j]);}printf("\n");}printf("\n");fclose(HFM_f);}4.调试结果输入26个字符及其权值26个字母的编码如下:译码如下:打印文件中的内容:打印出的哈夫曼树如下:5.时间复杂度本代码的哈夫曼算法的时间复杂度为O(n^3)。
哈夫曼编码与译码课程设计
目录第1章需求分析 (1)第2章总体设计 (1)第3章抽象数据类型定义 (2)3.1 哈夫曼编码与译码抽象数据类型的设计 (2)第4章详细设计 (2)4.1 工程视图 (2)4.2 类图视图 (3)4.3 函数的调用关系 (3)4.4 主程序流程图 (4)4.5 主要算法的流程图 (5)第5章测试 (7)第6章总结 (8)附录:程序代码 (9)第1章需求分析Huffman编码和译码根据给定的字符集和各字符的频率值,求出其中给定字符Huffman编码,并针对一段文本(定义在该字符集上)进行编码和译码,实现一个Huffman编码/译码系统。
要求设计类(或类模板)来描述Huffman树及其操作,包含必要的构造函数和析构函数,以及其他能够完成如下功能的成员函数:求Huffman编码输入字符串,求出编码输入一段编码,实现译码并设计主函数测试该类。
第2章总体设计图2.1主函数:对输入的字符段进行存储,并对字符数和对应的权值(字符个数)进行统计存储。
哈夫曼树初始化函数:对给定的字符数和权值,创建一棵哈夫曼树。
权值大小比较函数:找到每次所给集合的最小值和次小值,并返回给哈夫曼树初始化函数。
哈夫曼树编码函数:对创建的哈夫曼树,为左孩子的赋值为0,右孩子赋值为1,然后对叶子结点依次编码。
哈夫曼树译码函数:对输入的01二进制数一一与叶子结点的编码依次比较匹配。
第3章抽象数据类型定义3.1哈夫曼编码与译码抽象数据类型的设计enum Child{none,lchild,rchild}; //采用枚举,标记是左孩子还是右孩子class element //元素类{public://类的公有成员elememt(); //构造函数void change(char l,char *c,int p,Child h,int w) //对对象进行修改操作void getparent(int p) //对父结点的值进行修改操作void geta(Child h) //对孩子结点进行修改操作void getweight(int w) //对权值进行修改操作int returnweight() //返回权值操作friend void Select(element h[],int k,int *a,int *b);//友元函数的声明friend void HuffmanTreeCode(element HT[]);friend void HuffmanTreeYima(element huff[],char cod[],int b);private://类的私有成员char letter,*code; //letter为字符,*code指向编码字符串int weight; //权值int parent; //父结点Child a; //为父结点的左孩子还是右孩子};第4章详细设计4.1工程视图图4.1工程视图4.2 类图视图图4.2类图视图4.3 函数的调用关系 如下图:图4.3函数调用关系图主函数main()哈夫曼初始化函数 InitHuffmanTree () 寻找最小和次小结点函数 Select() 字符编码函数 HuffmanTreeCode () 字符译码函数 HuffmanTreeYima ()4.4主程序流程图4.5主要算法的流程图图4.5.1哈夫曼编码函数图4.5.2哈夫曼译码函数图5.1哈夫曼编码与译码这次课程设计写得比较仓促,程序许多处仍需要完善和修改。
数据结构 课程设计之哈夫曼编码
(一) 哈夫曼树的设计思想对于一组具有确定权值的叶子结点可以构造出多个具有不同带权路径长度的二叉树,其中具有最小带权路径长度的二叉树称作哈夫曼树或者最优二叉树。
首先给定n 个权值创造n 个只含根结点的二叉树,得到一个二叉树林;再在这二叉树林里面找根结点的权值最小和次小的两棵树作成新的二叉树,其中新的二叉树的根结点的权值为摆布子根结点权值之和;最后在二叉树林中把组合过的二叉树删除,再重复第二步,直到最后就剩一颗二叉树的时候得到的这棵二叉树就是哈夫曼树。
(二)哈夫曼编码与解码的设计思想在数据通讯中,时常要将传送的文字转换为二进制字符0 和1 组成的二进制串,称这个过程为编码。
与子相对的是解码或者是译码,就是用与编码相同的方式将二进制串转换称编码前的文字的过程称作解码。
在这里是通过哈夫曼树实现编码与解码的,所以称作是哈夫曼编码与解码。
首先输入一个字符串,还有相应的在哈夫曼树里的权值,这样用哈夫曼树把字符串用二进制串代替它,这个过程要注意树和编码问题,其中树的问题在上面已经解决,主要看编码的问题,就是根据我们输入的字符串和权值建立相应的树模型,这一步完成那编码就已经完成为了,最后打印就行了;然后就是解码,完成编码相应的解码就相对简单了,就是先找到在编码的时候建的那个模型树,将编码中的二进制串再根据权值转换为相应的字符串,这样一步步解码就行了。
以上就是通过用哈夫曼树进行哈夫曼编码与解码如何实现的主要设计思想。
(一)哈夫曼树的流程图不 是图 1 哈夫曼树的流程图(二)编码与解码的流程图图 2 编码与解码的流程图图片说明: (左边)编码流程图, (右边)解码流程图。
开始输入字符串判断权值 建立路径有最小和次小 循环建立二叉树根据树对路径分左 0右 1写出对应结点的编码结束开始初始化哈夫曼链表二叉树林找最小和次小 的二叉树组合成新的二叉树 删除用过的二叉树是不是最后一 个二叉树是结束开始找到树的根结点 输入二进制串扫描根据树的路径打印对应字符继续扫描 是否结束是输出字符串结束否下面给出的是用中缀转后缀算法实现的程序的源代码:#include "stdio.h"#include "string.h"#define MAX 100struct HaffNode{int weight;int parent;char ch;int lchild;int rchild;}*myHaffTree;struct Coding{char bit[MAX];char ch;int weight;}*myHaffCode;void Haffman(int n){int i,j,x1,x2,s1,s2;for (i=n+1;i<=2*n-1;i++) {s1=s2=10000;x1=x2=0;for (j=1;j<=i-1;j++)/*定义常量*//*权值*//*双亲结点下标*//*构造哈夫曼树*//*定义数组*//*字符的权值*//*定义结构体*//*定义哈夫曼函数*//*树的初始化*//*构造哈夫曼树的非叶子结点*/{if(myHaffTree[j].parent==0&&myHaffTree[j].weight<s1){s2=s1;x2=x1;s1=myHaffTree[j].weight;x1=j;/*分配摆布结点*/}else if(myHaffTree[j].parent==0&&myHaffTree[j].weight<s2){s2=myHaffTree[j].weight;x2=j;}}myHaffTree[x1].parent=i;myHaffTree[x2].parent=i;myHaffTree[i].weight=s1+s2;myHaffTree[i].lchild=x1;myHaffTree[i].rchild=x2;/*摆布子组合为新树*/}}void HaffmanCode(int n){int start,c,f,i,j,k;char *cd;/*构造n 个结点哈夫曼编码*/cd=(char *)malloc(n*sizeof(char));myHaffCode=(struct Coding *)malloc((n+1)*sizeof(struct Coding));cd[n-1]='\0';for(i=1;i<=n;++i) /*n 个叶子结点的哈夫曼编码*/ {start=n-1;for(c=i,f=myHaffTree[i].parent;f!=0;c=f,f=myHaffTree[f].parent)if(myHaffTree[f].lchild==c) cd[--start]='0';else cd[--start]='1';for(j=start,k=0;j<n;j++){myHaffCode[i].bit[k]=cd[j];k++;}myHaffCode[i].ch=myHaffTree[i].ch; myHaffCode[i].weight=myHaffTree[i].weight; }free(cd);}Init(){int i,n,m;printf("please input the number of words:"); scanf("%d",&n); /*取编码对应的权值*//*定义有返回值的函数*/m=2*n-1;myHaffTree=(struct HaffNode *)malloc(sizeof(struct HaffNode)*(m+1)); for(i=1;i<=n;i++){printf("please input the word and the equal:");scanf("%s%d",&myHaffTree[i].ch,&myHaffTree[i].weight); myHaffTree[i].parent=0;myHaffTree[i].lchild=0;myHaffTree[i].rchild=0;}for(i=n+1;i<=m;i++){myHaffTree[i].ch ='#';myHaffTree[i].lchild=0;myHaffTree[i].parent=0;myHaffTree[i].rchild=0;myHaffTree[i].weight=0;}Haffman(n);HaffmanCode(n);for(i=1;i<=n;i++){printf("%c %d",myHaffCode[i].ch,myHaffCode[i].weight); printf("\n");}printf("init success!\n");return n;}void Caozuo_C(int m){int n,i,j;char string[50],*p;printf("please input the words :"); scanf("%s",string);n=strlen(string);for(i=1,p=string;i<=n;i++,p++){for(j=1;j<=m;j++)if(myHaffCode[j].ch==*p)printf("%s\n",myHaffCode[j].bit); }}void Caozuo_D(int n){int i,c;char code[1000],*p;printf("please input the coding:"); scanf("%s",code);for(p=code,c=2*n-1;*p!='\0';p++) {if(*p=='0'){c=myHaffTree[c].lchild;if(myHaffTree[c].lchild==0){printf("%c",myHaffTree[c].ch);c=2*n-1;continue;/* 编码函数*//*计算字符串长度*/ /*进行编码*//*解码函数*//*输入二进制编码*//*进行解码*//*结束条件*//*赋值*//* 扫描*//*结束*/}}else if(*p=='1'){c=myHaffTree[c].rchild;if(myHaffTree[c].lchild==0){printf("%c",myHaffTree[c].ch);c=2*n-1; /*赋值*/continue;}}}printf("\n");}void main(){int n;char char1;n=Init();printf("A.coding B.codeprintingwhile(1){scanf("%c",&char1);if(char1=='c')break;switch(char1){case'A':Caozuo_C(n);break;case'B':Caozuo_D(n);break;case'C':;break;}}}/*主函数*//*定义字符*//*函数的调用*/C.exit\nplease input the process:\n");/*判断字符*//*执行编码操作*//*执行解码操作*/哈夫曼编码与解码的实现(一)中缀转后缀算法的运行结果:这部份我主要遇到了如下三个问题,其内容与解决方法如下所列:问题1:刚开始不知道如何建一个好树,因为我开始试着建了几个二叉树,不知道什么原因运行的时候那编码总是不对,跟在草稿纸上自己画的那个二叉树总是不相符,就找原因。
哈夫曼编码课程设计
目录1设计内容与设计要求 (1)1.1系统的基本功能 (2)1.2系统的设计要求 (2)2 系统需求分析 (1)2.1系统设计目标 (1)2.2哈夫曼算法 (1)3系统的实现 (3)4 程序调试 (3)5 总结 (3)5.1本系统特色 (3)5.2心得体会 (3)附件:源程序清单 (5)1设计内容与设计要求1.1系统的基本功能哈夫曼编码是根据字符出现频率对数据进行编码解码,以便对文件进行压缩的一种方法,目前大部分有效的压缩算法(如MP3编码方法)都是基于哈夫曼编码的。
数据压缩过程称为编码,也就是把文件中的每个字符均转换为一个唯一的二进制串。
数据解压过程称为解码,也就是把给定的二进制位字符串转换为对应的字符。
1.2系统的设计要求(1)数据结构可以使用结构体数组或结构体链表实现,结构体的属性可进行扩充。
(2)由用户输入相应文本。
(3)对于系统运行时,要求有相应的提示信息,方便用户进行选择。
2 系统需求分析2.1系统设计目标(1)哈夫曼树的建立。
(2)哈夫曼编码的生成。
(3)求出平均查找长度。
(4)用户输入权值的个数。
(5)输出的形式为整型。
(6)程序的执行可使用户在输入一列数值后,可得到由这些权值所得到的编码。
2.2 哈夫曼算法哈夫曼算法流程如下:(1)根据给定的N个权值{W1,W2,····,WN}构成N棵二叉树的集合F={T1,T2,T3,···,Tn},其中每棵二叉树Ti中只有一个带权为Wi的根节点,其左右子树均空。
(2)在F中选取两颗根节点的权值最小的树作为左右子树构造一棵新的二叉树,且置新的二叉树的根结点的权值最小的树为其左右子树上根节点的权值之和。
(3)在F中删除这两棵树,同时将新得到的二叉树加入F中。
(4)重复(2)和(3),直到F只含一棵树为止。
这棵树便是哈夫曼树。
(5)约定左分支表示字符‘0’,右分支表示字符‘1’,则可以从根结点到叶子结点的路径上分支字符组成的字符串作为该叶子结点字符的编码,这就是哈夫曼编码。
数据结构课程设计哈夫曼编码实验
数据结构设计性实验Huffman编码与译码学号姓名班级设计性实验—Huffman 编码与译码一.实验目的:在掌握相关基础知识的基础上,学会自己设计实验算法,熟练掌握Huffman 树的建立方法,Huffman 编码的方法,进而设计出Huffman 译码算法,并编程实现。
二.实验要求:在6学时以内,制作出能够实现基于26个英文字母的任意字符串的编译码。
写出技术工作报告并附源程序。
三.实验内容及任务:1.设字符集为26个英文字母,其出现频度如下表所示。
2.建Huffman 树; 3.利用所建Huffman 树对任一字符串文件进行编码——即设计一个Huffman 编码器;4.对任一字符串文件的编码进行译码——即设计一个Huffman 译码器。
实现步骤:1.数据存储结构设计; 2.操作模块设计; 3.建树算法设计; 4.编码器设计;5. 译码器设计;51 48 1 15 63 57 20 32 5 1频度z y x w v u t 字符11611882380频度p 21 f q15 g r 47 h s o n m l k j 字符 57 103 32 22 13 64 186 频度 i e d c b a 空格 字符四.分析以及算法描述1.分析问题1)首先学习二叉树的知识,了解二叉树的路径、权数以及带权路径长度计算。
2)认识霍夫曼树,了解霍夫曼树的定义,构造霍夫曼树构造算法①又给定的n个权值{w1,w2,w3,……,w n}构造根节点的二叉树,从而得到一个二叉树森林F={T1,T2,T3,……T n}。
②在二叉树森里选取根节点全职最小和此最小的两棵二叉树作为左右节点构造新的二叉树,此时新的二叉树的根节点权值为左右子树权值之和。
③在二叉树森林中删除作为新二叉树的根节点左右子树的两棵二叉树,将新的二叉树加入到二叉树森林F中。
④重复②和③,当二叉树森林F只剩下一棵二叉树时,这棵二叉树是所构造的霍夫曼树。
3)练习通过普通树来构造霍夫曼树。
课程设计哈夫曼编码
《数据结构》课程设计报告设计题目哈夫曼(Huffman)编译码器学院名称信息工程学院专业班级 13计本1 姓名 hhh学号1312219999目录一、实验题目-哈夫曼(Huffman)编/译码器 ------------------------------二、问题描述-----------------------------------------------三、设计目标-----------------------------------------------四、需求分析-----------------------------------------------五、概要设计-----------------------------------------------1---系统结构图--------------------------------------2--各个模块功能的详细描述------------------------------- 六、详细设计-----------------------------------------------1——详细代码--------------------------------------a)头文件代码--------------------------------------b)主函数代码--------------------------------------2——系统流程图--------------------------------------七、测试分析-----------------------------------------------八、使用说明-----------------------------------------------1、白盒-----------------------------------------------2、黑盒-----------------------------------------------九、课程设计总结----------------------------------------------一、实验题目哈夫曼(Huffman)编/译码器二、问题描述利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。
课程设计--哈夫曼编码与译码
哈夫曼编码与译码学生姓名:指导老师:摘要本课程设计主要解决的是利用哈夫曼树生成的哈夫曼编码进行字符串的加密和解密,并将加密的编码写入文件。
在此课程设计中,系统开发平台为Windows XP,程序设计语言采用面向过程的高级语言C和面向对象的高级语言C++,程序运行平台为Visual C++ 6.0。
在程序设计中,采用了结构化与面向过程两种解决问题的方法。
程序通过调试运行,初步实现了设计目标,并且经过适当完善后,将可以应用在商业中解决实际问题。
关键词哈夫曼树,编码,译码,文件操作,C,C++;1 引言1.1 课题背景随着信息时代的到来,各种信息日益丰富,信息迅速膨胀,对信息管理的工作量也日益增大。
在信息化未到来之前,信息的存储编码也变得尤为重要,公司之间的信息需要编码,用户个人数据需要编码,都需要占用很大的空间,所以一个好的、高效的编码译码算法是十分重要的。
好的加密算法不仅可以降低管理方的工作量和存储量,还可以对用户的信息进行高效的管理,同时使在用中可以避免不必要的麻烦。
数据结构是指相互之间存在一定关系的数据元素的集合。
按照视点的不同,数据结构分为逻辑结构和存储结构。
数据的逻辑结构(logical structure)是指数据元素之间逻辑关系的整体。
所谓逻辑关系是指数据元素之间的关联方式或邻接关系。
根据数据元素之间逻辑关系的不同,数据结构分为四类:集合、线性结构、树结构、图结构。
数据的逻辑结构属于用户视图,是面向问题的,反映了数据内部的构成方式。
为了区别于数据的存储结构,常常将数据的逻辑结构称为数据结构。
数据的存储结构(storage structure)又称为物理结构,是数据及其逻辑结构在计算机中的表示,换言之,存储结构除了数据元素之外,必须隐式或显示地存储数据元素之间的逻辑关系。
通常有两种存储结构:顺序存储结构和链接存储结构。
树是一种在实际应用中被广泛使用的数据结构。
它是由同一类型的记录构成的集合。
c哈夫曼编码课程设计
c 哈夫曼编码课程设计一、课程目标知识目标:1. 学生能理解哈夫曼编码的基本原理,掌握其构建过程和应用场景。
2. 学生能运用哈夫曼编码进行数据压缩,并了解压缩比的概念。
3. 学生能理解哈夫曼编码在通信、图像处理等领域的重要性。
技能目标:1. 学生能够运用所学知识,独立构建哈夫曼树并进行编码。
2. 学生能够分析给定数据,选择合适的编码方法进行数据压缩。
3. 学生能够运用编程工具实现哈夫曼编码和解码过程。
情感态度价值观目标:1. 学生通过学习哈夫曼编码,培养对数据压缩技术的兴趣,提高信息素养。
2. 学生在合作学习过程中,培养团队协作能力和沟通能力。
3. 学生了解我国在数据压缩领域的研究成果,增强民族自豪感。
课程性质:本课程为信息技术课程,旨在帮助学生掌握数据压缩的基本方法,提高数据处理能力。
学生特点:学生处于高年级阶段,具备一定的编程基础和逻辑思维能力。
教学要求:结合学生特点和课程性质,注重理论与实践相结合,培养学生的实际操作能力和创新能力。
通过分解课程目标为具体学习成果,使学生在学习过程中能够明确自身的学习进度和目标。
二、教学内容1. 哈夫曼编码基本原理:介绍哈夫曼编码的概念、原理和优势,结合教材相关章节,使学生理解哈夫曼编码在数据压缩中的应用。
- 哈夫曼树的构建方法- 哈夫曼编码的生成过程- 压缩比的概念及其计算方法2. 哈夫曼编码的实际操作:通过实际操作,让学生掌握哈夫曼编码的构建和编码过程。
- 利用编程工具实现哈夫曼树的构建- 编程实现哈夫曼编码的生成- 数据压缩与解压缩的实际操作3. 哈夫曼编码的应用案例分析:结合教材案例,分析哈夫曼编码在通信、图像处理等领域的作用。
- 通信领域的数据压缩- 图像处理中的哈夫曼编码应用- 其他领域中的应用案例4. 编程实践:布置相关编程任务,巩固学生对哈夫曼编码的理解和应用。
- 实现哈夫曼编码的压缩和解压缩程序- 分析不同数据集的压缩效果,优化哈夫曼编码方法教学内容安排和进度:第1课时:哈夫曼编码基本原理及构建方法第2课时:哈夫曼编码的实际操作(构建哈夫曼树、生成编码)第3课时:哈夫曼编码的应用案例分析第4课时:编程实践(实现压缩与解压缩程序,优化编码方法)三、教学方法本课程将采用以下教学方法,以促进学生的主动参与和深入理解:1. 讲授法:对于哈夫曼编码的基本原理和概念,通过教师清晰的讲解,结合教材内容,使学生快速掌握理论基础。
(完整word版)数据结构课程设计(哈夫曼编码)
目录目录 (1)1 课程设计的目的和意义 (3)2 需求分析 (5)3 系统设计 (6)(1)设计思路及方案 (6)(2)模块的设计及介绍 (6)(3)主要模块程序流程图 (9)4 系统实现 (14)(1)主调函数 (14)(2)建立HuffmanTree (14)(3)生成Huffman编码并写入文件 (18)(4)电文译码 (19)5 系统调试 (22)小结 (25)参考文献 (26)附录源程序 (27)1 课程设计的目的和意义在当今信息爆炸时代,如何采用有效的数据压缩技术来节省数据文件的存储空间和计算机网络的传送时间已越来越引起人们的重视。
哈夫曼编码正是一种应用广泛且非常有效的数据压缩技术。
哈夫曼编码的应用很广泛,利用哈夫曼树求得的用于通信的二进制编码称为哈夫曼编码。
树中从根到每个叶子都有一条路径,对路径上的各分支约定:指向左子树的分支表示“0"码,指向右子树的分支表示“1”码,取每条路径上的“0”或“1"的序列作为和各个对应的字符的编码,这就是哈夫曼编码。
通常我们把数据压缩的过程称为编码,解压缩的过程称为解码。
电报通信是传递文字的二进制码形式的字符串。
但在信息传递时,总希望总长度尽可能最短,即采用最短码。
作为软件工程专业的学生,我们应该很好的掌握这门技术。
在课堂上,我们能过学到许多的理论知识,但我们很少有过自己动手实践的机会!课程设计就是为解决这个问题提供了一个平台。
在课程设计过程中,我们每个人选择一个课题,认真研究,根据课堂讲授内容,借助书本,自己动手实践。
这样不但有助于我们消化课堂所讲解的内容,还可以增强我们的独立思考能力和动手能力;通过编写实验代码和调试运行,我们可以逐步积累调试C程序的经验并逐渐培养我们的编程能力、用计算机解决实际问题的能力。
在课程设计过程中,我们不但有自己的独立思考,还借助各种参考文献来帮助我们完成系统。
更为重要的是,我们同学之间加强了交流,在对问题的认识方面可以交换不同的意见.同时,师生之间的互动也随之改善,我们可以通过具体的实例来从老师那学到更多的实用的知识。
哈夫曼算法课程课程设计
哈夫曼算法课程课程设计一、教学目标本课程旨在通过哈夫曼算法的教学,让学生了解和掌握数据压缩中的一种重要算法,培养学生分析和解决问题的能力。
1.了解哈夫曼算法的原理和特点。
2.掌握哈夫曼编码和解码的过程。
3.理解哈夫曼算法在数据压缩中的应用。
4.能够运用哈夫曼算法对数据进行编码和解码。
5.能够分析哈夫曼算法的性能,并与其他压缩算法进行比较。
情感态度价值观目标:1.培养学生对计算机科学和数据压缩的兴趣。
2.培养学生通过算法解决问题的方式,提高其创新思维。
二、教学内容本课程的教学内容主要包括哈夫曼算法的原理、编码和解码过程,以及其在数据压缩中的应用。
1.哈夫曼算法的原理:介绍哈夫曼算法的背景和基本思想,讲解算法的构建过程。
2.哈夫曼编码:讲解如何利用哈夫曼算法对数据进行编码,包括编码的步骤和注意事项。
3.哈夫曼解码:讲解如何利用哈夫曼算法对数据进行解码,包括解码的步骤和注意事项。
4.哈夫曼算法在数据压缩中的应用:介绍哈夫曼算法在数据压缩中的重要性,讲解如何运用哈夫曼算法进行数据压缩和解压缩。
三、教学方法为了更好地让学生理解和掌握哈夫曼算法,本课程将采用多种教学方法相结合的方式。
1.讲授法:讲解哈夫曼算法的原理、编码和解码过程,让学生了解算法的具体操作。
2.案例分析法:通过分析具体的案例,让学生了解哈夫曼算法在实际应用中的作用。
3.实验法:安排实验课,让学生亲自动手进行哈夫曼编码和解码,加深对算法的理解。
四、教学资源为了保证教学的质量和效果,我们将准备丰富的教学资源。
1.教材:选择权威、实用的教材,为学生提供系统的学习资料。
2.参考书:推荐学生阅读相关的参考书,拓展知识面。
3.多媒体资料:制作精美的PPT,生动形象地展示哈夫曼算法的原理和操作过程。
4.实验设备:准备充足的实验设备,确保每位学生都能在实验课中亲自动手操作。
五、教学评估为了全面、客观地评估学生的学习成果,本课程将采用多种评估方式。
1.平时表现:评估学生在课堂上的参与程度、提问和回答问题的表现,以及课堂作业的完成情况。
哈夫曼编码课程设计
摘要哈夫曼编码是广泛用于数据文件压缩的十分有效的编码方法。
其压缩通常在20%~90%之间。
哈夫曼编码算法使用字符在文件中出现的频率表来建立一个用0,1串表示各字符的最优表示方式。
哈夫曼算法构造的扩充二叉树称为哈夫曼编码树或哈夫曼树。
当然,还有编码和译码部分。
本系统的前端开发工具是Visual C++6.0。
具有输入字符集大小及权值大小,构造哈夫曼树,并对用户输入的字符串进行编码以及译码还有退出四种功能。
本程序经过测试后,功能均能实现,运行稳定。
关键词:哈夫曼树,编码,译码,权值目录1问题描述 (1)2 问题分析 (2)3算法设计 (3)4算法实现 (4)5测试分析 (7)结论 (9)参考文献 (9)1 问题描述哈夫曼在上世纪五十年代初就提出这种编码时,根据字符出现的概率来构造平均长度最短的编码。
它是一种变长的编码。
哈夫曼编码应用广泛,如JPEG中就应用了哈夫曼编码。
在编码中,若各码字长度严格按照码字所对应符号出现概率的大小的逆序排列,则编码的平均长度是最小的。
构造好哈夫曼树后,就可根据哈夫曼树进行编码。
然而怎样构造一棵哈夫曼树呢?最具有一般规律的构造方法就是哈夫曼算法。
字符根据其出现的概率作为权值构造一棵哈夫曼树后,经哈夫曼编码得到的对应的码值。
只要使用同一棵哈夫曼树,就可把编码还原成原来那组字符。
显然哈夫曼编码是前缀编码,即任一个字符的编码都不是另一个字符的编码的前缀,否则,编码就不能进行翻译。
利用哈夫曼算法的编码和译码功能,重复地显示并处理以下项目,即构造哈夫曼树,编码及译码几项功能,直到选择退出为止。
本次设计就是为这样的一个哈夫曼的编/译码器。
哈夫曼编码所以能产生较短的码文,是因为哈夫曼树具有最小加权路径长度的二叉树。
如果叶结点的权值恰好是某个需编码的文本中各字符出现的次数,则编码后文本的长度就是该哈夫曼树的加权路径长度。
译码过程为自做向右逐一扫描码文,并从哈夫曼树的根开始,将扫到的二进制位串中的相邻位与哈夫曼树上标的0,1相匹配,以确定一条从根到叶子结点的路径,一旦到达叶子,则译出了一个字符。
课程设计报告哈夫曼编码
课程设计题目哈夫曼编码学院计算机科学与技术专计算机科学与技术业班级姓名指导教师20 0 010 年7 月2 日课程设计任务书学生姓名:拉巴珠久专业班级:计算机0806指导教师:姚寒冰工作单位:计算机科学系题目:哈夫曼编码初始条件:输入一段英文字符,试为该文中的每个字符编制相应的哈夫曼码。
(1) 1:初始化(Initialization )。
对输入的一段央文中的每个字符统计其权值,建立哈夫曼树;(2) E:编码(Encoding )。
利用已建好的哈夫曼树,对每个字符进行编码。
(3) D:译码(Decoding )。
利用已建好的每个编码,对输入的一个由0、1组成的序列进行译码;(4) P:印代码文件(Print )。
将每个字符编的哈夫曼码和译码结果显示在终端上。
测试用例见题集p149。
要求完成的主要任务:(包括课程设计工作量及其技术要求,以及说明书撰写等具体要求) 课程设计报告按学校规定格式用A4纸打印(书写),并应包含如下内容:1、问题描述简述题目要解决的问题是什么。
2、设计存储结构设计、主要算法设计(用类C语言或用框图描述)、测试用例设计;3、调试报告调试过程中遇到的问题是如何解决的;对设计和编码的讨论和分析。
4、经验和体会(包括对算法改进的设想)5、附源程序清单和运行结果。
源程序要加注释。
如果题目规定了测试数据,则运行结果要包含这些测试数据和运行输出,6、设计报告、程序不得相互抄袭和拷贝;若有雷同,则所有雷同者成绩均为0分。
时间安排:1、第18周(6月28日至7月2日)完成。
2、7月2日08 : 30到计算中心检查程序、交课程设计报告、源程序( CD盘)。
指导教师签名:年月日系主任(或责任教师)签名:年月日目录1设计题目 (1)2问题描述 (1)3.1数据结构设计 (1)3.2主要算法设计 (3)3.3测试用例设计 (6)4调试报告 (7)5结束语 (7)六、课程设计参考资料 (8)附录 (9)F1源代码 (9)F2运行结果 (16)哈夫曼编码1设计题目哈夫曼编码2问题描述输入一段英文字符,试为该文中的每个字符编制相应的哈夫曼码。
huffman哈夫曼树编码译码课程设计报告
数据结构课程设计信息科学与工程学院:学院计算机科学与技术专业:1601 计卓级:班号:学:学生姓名指导教师:23/ 1年月日题目名称一、实验内容哈夫曼编码译码系统【问题描述】用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。
但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(复原)。
对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。
试为这样的信息收发站写一个哈夫曼码的编/译码系统。
【基本要求】1)初始化。
从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树。
2)编码。
利用已建好的哈夫曼树对输入英文进行编码,编码结果存储在数组中。
3)译码。
利用已建好的哈夫曼树将数组中的代码进行译码,结果存入一个字符数组。
4)输出编码。
将编码结果显示在终端上,每行50个代码。
5)输出哈夫曼树。
将哈夫曼树以直观的方式(树或凹入表形式)显示出来。
【实现提示】用户界面可以设计为“菜单”方式,再加上一个“退出”功能。
请用户键入一个选择功能符。
此功能执行完毕后再显示此菜单,直至某次用户选择了“退出”为止。
参考教材P240-246【选做内容】将哈夫曼树保存到文件中,编码和译码的结果也分别存放在两个文本文件中。
23/ 2二、数据结构设计储存结构struct HNodeType {//字符结构体类型int weight;//权int parent;//双亲位置int lchild;//左孩子int rchild;//右孩子char inf;// 字符};struct HcodeType {存储编码int bit[MaxBit];// int start;// 起始位置};三、算法设计1、在构造哈夫曼树时,设计一个结构体数组HuffNode保存哈夫曼树中各结点的信息,根据二叉树的性质可知,具有n个叶子结点的哈夫曼树共有2n-1个结点,所以数组HuffNode的大小设置为2n-1。
哈弗曼编码解码器(课程设计)
//课程设计:哈弗曼编码解码器及报告书//vc6测试可以//运行的条件是:“yasuo.txt”, “yima.txt”, “jieya.txt”存在,要压缩的信息已存//在了其他一个文本文档中,然后根据提示输入要压缩的文本文件名,输入的文件名要//加.txt扩展名,如:a.txt。
//write by dlnu.ZJY#include <iostream>#include <fstream>#define Max 50#define MAX 10000using namespace std;struct tree//存储统计的频率和字母的{char word;int rare;};struct Bianma//存各字母所对应的编码的{char word;int code[Max];};struct element//哈弗曼树的{tree weight;int lchild;int rchild;int parent;int flag;int yezi;};//__________________________________全局变量element huffTree[103];Bianma bianma[52];int zijie, wei, yushu;char filename[50];//___________________________________class HuffmanTree{public:void open(); //打开要编码文件并统计字母出现的频率函数void creat(); //构造哈弗曼树函数int select(int k); //找权值最小根节点函数void coding(); //编码函数void decoding(); //将编码后信息存入文件函数void original(); //对已压缩文件解压并译码函数void compare(); //压缩函数void yasuoxianshi(); //显示压缩信息void jieyaxianshi(); //显示解压信息void xianshi(); //显示文件压缩比void menu(); //菜单};//_____________________________________________________________________________ ______________________void HuffmanTree::open()//打开文件并统计频率{char ch;int i, n, j = 0, flag = 0;for(i = 0; i < 103; i++)//初始化{huffTree[i].weight.rare = 0;huffTree[i].weight.word = 0;huffTree[i].yezi = 0;}cout<<"请输入您要压缩的文件名:"<<endl;cin>>filename;ifstream infile(filename, ios::out);//打开文件if(!infile){flag=1;cerr<<"文件打开失败!"<<endl;exit(1);}if(flag == 0){cout<<"压缩中,请等待……"<<endl<<endl<<endl;}while(infile.get(ch))//统计频率{if(ch >= 65 && ch <= 90)//65~90{i = ch - 65;huffTree[i].weight.rare++;huffTree[i].yezi = 1;}if(ch >= 97 && ch <= 122)//97~122{n = ch - 71;huffTree[n].weight.rare++;huffTree[n].yezi = 1;}}infile.close();}//_____________________________________________________________________________ ________________________void HuffmanTree::creat()//构造哈弗曼树{int i, k, i1, i2, n = 52, j;for(i = 0; i < 2*n-1; i++)//初始化{huffTree[i].parent = -1;huffTree[i].lchild = -1;huffTree[i].rchild = -1;huffTree[i].flag = 0;}for(i = 0; i < 26; i++)//字母赋值{huffTree[i].weight.word=i+65;}for(j = 0; j < 26; j++)//字母赋值{huffTree[j+26].weight.word = j+97;}for(k = n; k < 2*n-1; k++)//建树{i1 = select(k);i2 = select(k);huffTree[k].weight.rare = huffTree[i1].weight.rare + huffTree[i2].weight.rare;huffTree[i1].parent = k;huffTree[i2].parent = k;huffTree[k].lchild = i1;huffTree[k].rchild = i2;}}//_____________________________________________________________________________ ______________________int HuffmanTree::select(int k)//找出所有根节点中权值最小的根节点{int i, n = 52, min, rare = 10000;for(i = 0; i < k; i++){if((huffTree[i].weight.rare < rare) && (huffTree[i].flag == 0)){min = i;rare = huffTree[i].weight.rare;}}huffTree[min].flag = 1;return min;}//_____________________________________________________________________________ ____________________void HuffmanTree::coding()//对构造出的哈弗曼树编码{int e, a = 0, i, j, n = 52, p, parent;for(i = 0; i < n; i++)//初始化{for(j = 0; j < Max; j++){bianma[i].code[j] = -1;}bianma[i].word = 95;}for(i = 0; i < 2*n-1; i++)//根据建好的哈弗曼树对各字母编码,从叶子结点往上查,左1右0,将编好的码存入bianma[]中{if((huffTree[i].flag != 2) && (huffTree[i].yezi == 1)){e = Max - 1;huffTree[i].flag = 2;bianma[a].word = huffTree[i].weight.word;p = i;while(huffTree[p].parent != -1){parent = huffTree[p].parent;if(huffTree[parent].lchild == p){bianma[a].code[e] = 0;e--;}else if(huffTree[parent].rchild == p){bianma[a].code[e] = 1;e--;}p = huffTree[p].parent;//原来是这里的问题,以前parent两次赋值让每次编码都又往上跳了一级,所有编出的码有重复的}a++;}}}//_____________________________________________________________________________ _______________________void HuffmanTree::decoding()//将原文件重新编码后将编码后的存入文件{int i, j, n = 52;char ch;ifstream file(filename, ios::out);if(!file){cerr<<"文件打开失败!"<<endl;exit(1);}ofstream infile("bianma.txt", ios::in|ios::out|ios::trunc);//打开文件if(!infile){cerr<<"文件打开失败!"<<endl;exit(1);while(file.get(ch))//将编码后的信息存入bianma.txt文件{for(i = 0; i < n; i++){if(ch == bianma[i].word)for(j = 0; j < Max; j++)if(bianma[i].code[j] != -1){infile << bianma[i].code[j];}}}file.close();infile.close();}//_____________________________________________________________________________ ___________________________void HuffmanTree::compare()//压缩文件{char ch, a, yasuo[1000][8] = {95}, b[100000] = {0};int n = 0, i = 0, j, k = 0, l = 0;ifstream infile("bianma.txt", ios::out);//打开文件if(!infile){cerr<<"文件打开失败!"<<endl;exit(1);}ofstream outfile("yasuo.txt", ios::binary|ios::trunc);//打开文件if(!outfile){cerr<<"open error!" <<endl;abort();}while(infile.get(ch))//统计0,1个数{b[i] = ch;i++;}wei = i;zijie = wei / 8;yushu = wei % 8;if(yushu != 0)zijie++;for(i = 0; i < zijie; i++)//将编码后的信息每八个倒着存入yaosuo[][]数组{for(j = 7; j >= 0; j--){yasuo[i][j] = b[k++];}}for(i = 0; i < zijie; i++)//压缩已编码的原文件,八个编码合为一个字节存入二进制文件{a = 0;for(j = 0; j < 8; j++)if(yasuo[i][j] != 95)if(yasuo[i][j] == '0' || yasuo[i][j] == '1'){if(yasuo[i][j] == '1'){a = (a << 1) | 1;}else if(yasuo[i][j] == '0'){a = a << 1;}}outfile.write((char *)&a, sizeof(a));}infile.close();outfile.close();}//_____________________________________________________________________________ ________________________void HuffmanTree::original()//对已压缩文件解压并译码{int i = 0, n = 52, p = 102, q = 102, k, j, f = 0, m = 0;char a, b, c, d, jieya[100000];ifstream infile("yasuo.txt", ios::binary);//打开文件if(!infile){cerr<<"文件打开失败!"<<endl;abort();}ofstream infile1("jieya.txt", ios::in|ios::out|ios::trunc);//打开文件if(!infile1){cerr<<"文件打开失败!"<<endl;exit(1);}for(k = 0; k < zijie; k++)//解压压缩了的二进制文件{infile.read((char*)&a, sizeof(a));for(j = 0; j < 8; j++){if(m >= wei){break;}b = a;c = ((b >> 1) << 1);//先右移再左移将最右端的位变为0d = (a - c) + '0';//得出最右端的二进制位a = a >> 1;if(d == '0'){jieya[f++] = '0';//将解压后的信息先存入jieya[]数组}else if(d == '1'){jieya[f++] = '1';//将解压后的信息先存入jieya[]数组}m++;}}for(int z = 0; z < wei + 1; z++)//译码,从树的根结点开始判断,左1右0,直到找到叶子结点{if(jieya[z] == '0'){i = huffTree[p].lchild;p = huffTree[p].lchild;if(huffTree[i].weight.word != 0){infile1 << huffTree[i].weight.word;p = q;}}else if(jieya[z] == '1'){i = huffTree[p].rchild;p = huffTree[p].rchild;if(huffTree[i].weight.word != 0){infile1 << huffTree[i].weight.word;p = q;}}}infile.close();infile1.close();}//_____________________________________________________________________________ _____________________________void HuffmanTree::yasuoxianshi()//显示压缩的信息{char ch;int i, j, n = 52, k = 0;ifstream infile(filename, ios::out);//打开文件if(!infile){cerr<<"文件打开失败!"<<endl;exit(1);}cout<<"原文件:"<<endl;while(infile.get(ch))//输出原文件{cout << ch;}cout << endl << endl;infile.close();cout<< "根据哈弗曼树对字母的编码:"<<endl;for(i = 0; i < n; i++)//输出各字母对应的编码{if(bianma[i].word != 95){for(j = 0; j < Max; j++)if(bianma[i].code[j] != -1)cout<< bianma[i].code[j];//编码cout<<" "<<bianma[i].word<<endl;//字母}}cout<< endl;ifstream infile2("bianma.txt", ios::out);//打开文件if(!infile2){cerr<<"文件打开失败!"<<endl;exit(1);}cout<<"对原文件编码后的文件:"<<endl;while(infile2.get(ch))//输出对原文件编码后的信息{cout<< ch;}cout<< endl<< endl;cout<< "压缩成功!"<<endl<<endl;cout<< "压缩后的文件名为:"<< "yasuo.txt"<< endl<< endl;}//_____________________________________________________________________________ _____________________________void HuffmanTree::jieyaxianshi()//显示解压的信息{char ch;ifstream infile3("jieya.txt", ios::out);//打开文件if(!infile3){cerr<<"文件打开失败!"<<endl;exit(1);}cout<<"解压成功!"<<endl<<endl;cout<<"解压后的文件名为: "<<"jieya.txt"<<endl<<endl;cout<<"解压并译码后的文件:"<<endl;while(infile3.get(ch))//输出解压后的信息{cout << ch;}cout<<endl<<endl;}//_____________________________________________________________________________ _____________________________void HuffmanTree::xianshi()//显示压缩比的信息{int k = 0;char ch;ifstream infile4(filename, ios::out);//打开文件if(!infile4){cerr<<"文件打开失败!"<<endl;exit(1);}while(infile4.get(ch))//统计原文件字母个数{k++;}cout<<"本次文件的压缩比为:"<<endl;cout<<"原文件"<<" "<<"压缩后的文件"<<endl;cout<<" "<< k <<" "<<":"<<" "<<zijie<<endl<<endl;if(k > zijie)//判断压缩前后文件的大小看压缩是否成功{cout<<"压缩成功!"<<endl<<endl;cout<<"压缩率为:"<<((double)zijie/(double)k)*100<<"%"<<endl<<endl;}elsecout<<"压缩失败!"<<endl<<endl;}//_____________________________________________________________________________ _____________________________void HuffmanTree::menu()//主菜单{cout<<" 欢迎使用哈弗曼编码器& 译码器"<<endl;cout<<"<<----------------------------------------------------------------->>"<<endl;cout<<" 请选择您需要的操作:"<<endl;cout<<" ┍━━━━━━━━━━━━━━━━━━━━┑"<<endl;cout<<" ││"<<endl;cout<<" │ 1.压缩文件│"<<endl;cout<<" │ 2.解压文件│"<<endl;cout<<" │ 3.显示压缩比│"<<endl;cout<<" │ 4.退出│"<<endl;cout<<" ││"<<endl;cout<<" ┕━━━━━━━━━━━━━━━━━━━━┙"<<endl<<endl;}//_____________________________________________________________________________ _____________________________int main(){HuffmanTree tree;int choose;while(1){tree.menu();cin>>choose;cout<<endl;switch(choose){case 1://压缩文件tree.open();tree.creat();tree.coding();tree.decoding();pare();tree.yasuoxianshi();system("pause");system("cls");break;case 2://解压文件tree.original();tree.jieyaxianshi();system("pause");system("cls");break;case 3://显示压缩比tree.xianshi();system("pause");system("cls");break;case 4://退出cout<<"谢谢使用!"<<endl;exit(0);default:cout<<"输入错误,请重新输入!"<<endl;system("pause");system("cls");break;}}return 0;}题目:设计Huffman 编码器与解码器(**)1、问题描述 (15)2.需求分析 (15)3.概要设计 (15)(1)抽象数据类型: (15)(2)主程序流程: (15)(3)模块调用关系: (16)4.详细设计 (17)(1)实现概要设计的数据类型: (17)(2)主程序以及其它模块的算法描述: (17)主函数具体代码: (17)(3)其它模块的算法描述 (18)创建哈弗曼树函数: (19)挑选权值最小的根节点函数: (19)据建好的哈弗曼树编码函数: (20)压缩文件主要代码: (21)解压文件主要代码: (21)译码主要代码: (22)5、编码与调试分析 (22)1.编码与调试过程中遇到的问题及解决办法: (22)2.待解决问题: (23)6、使用说明 (24)7、测试结果 (24)(1)压缩文件结果: (24)(2)解压文件结果: (25)(3)显示压缩比结果: (26)8、自学知识 (26)9、课程设计心得体会 (26)参考书: (27)1、问题描述利用哈夫曼编码进行信息通讯可以大大提高信道的利用率,缩短信息传输时间,降低传输成本。
哈夫曼编码译码课程设计
目录1.问题描述 (1)2.基本要求 (1)3.数据结构 (1)4.总体设计 (1)5.详细设计 (2)5.1主函数 void main() (2)5.2建立文件 void jianliwenjian() (3)5.3输入原文 void luruyuanwen() (4)5.4创建哈夫曼树 void chuangjian() (5)5.5编码 void bianma() (6)5.6对哈夫曼码译码 void yiwen() (7)5.7保存译文 void baocunyiwen() (8)5.8输出原文 void duquyuanwen() (9)5.9输出原文编码void duqubianma() (10)5.10输出译文 void duquyiwen() (11)6.测试与调试 (11)7.源程序清单 (8)8.实验心得 (28)1.问题描述打开一篇英文文章,统计该文章中每个字符出现的次数,然后以它们作为权值,设计一个哈夫曼编/译码系统。
2.基本要求以每个字符出现的次数为权值,建立哈夫曼树,求出哈夫曼编码,对文件yuanwen 中的正文进行编码,将结果存到文件yiwen中,再对文件yiwen中的代码进行译码,结果存到textfile中。
3.数据结构char CH[N]; //记录原文字符数组char YW[N]; //记录译文字符数组typedef char * Hcode[m+1]; //存放哈夫曼字符编码串的头指针的数组typedef struct{char a;int num;}dangenode; //记录单个字符的类别和出现的次数typedef struct{dangenode b[m];int tag;}jilunode; //统计原文出现的字符种类和数量typedef struct node //静态三叉的哈夫曼树的定义{int weight; //结点的权值int parent; //双亲的下标int Lchild; //左孩子结点的下标int Rchild; //右孩子结点的下标}htnode,hn[M+1]; // hn是结构数组类型,0号单元不用4.总体设计功能函数模块划分void main() //主函数void jianliwenjian() //建立存储原文的文件yuanwenvoid luruyuanwen() //通过程序录入原文到文件yuanwen中void min_2(hn ht,int n,int *tag1,int *tag2) //选择权值较小的两个结点void chuangjian(jilunode * jilu,hn ht) //建立哈夫曼树void bianma(jilunode * jilu,hn ht,Hcode hc,int n) //对原文进行编码void bianmabaocun(Hcode hc,jilunode * jilu) //保存编码在文件yiwen中void yiwen(Hcode hc,jilunode * jilu) //读取yiwen中的编码,并将其翻译为原文void baocunyiwen() //将翻译的译文保存到文件textfile中void duqubianma() //在编码文件yiwen中读取编码5.详细设计5.1主函数void main()5.2建立文件void jianliwenjian()首先,要建立一个文件来存储原文,在这里文件的名称按要求默认为yuanwen,文件建立时有可能成功,有可能失败,建立失败时输出“Cannot open file”,成功后会提示:“文件已建立,名称为yuanwen”。
c语言哈夫曼课程设计
c语言哈夫曼课程设计一、课程目标知识目标:1. 理解哈夫曼编码的基本原理,掌握哈夫曼树的结构特点及其构建方法;2. 学会运用C语言实现哈夫曼编码和解码过程;3. 了解哈夫曼编码在数据压缩中的应用及其优势。
技能目标:1. 能够运用所学知识,独立编写C语言程序构建哈夫曼树并进行编码和解码;2. 培养学生运用算法解决问题的能力,提高编程实践技能;3. 提高学生的逻辑思维能力和分析解决问题的能力。
情感态度价值观目标:1. 激发学生对计算机科学和信息技术的兴趣,培养良好的学习习惯;2. 培养学生的团队合作意识,提高沟通协作能力;3. 培养学生面对问题勇于探索、积极进取的精神。
本课程针对高中年级学生,结合C语言学科特点,充分考虑学生的认知水平、兴趣和实际需求,设计具有实用性、挑战性和趣味性的课程内容。
课程旨在帮助学生掌握哈夫曼编码的核心知识,提高编程实践能力,培养良好的学习态度和价值观,为后续计算机科学学习奠定基础。
通过本课程的学习,学生将能够独立完成哈夫曼编码相关程序的设计与实现,并在实际应用中发挥其优势。
二、教学内容1. 哈夫曼编码基本原理:介绍哈夫曼编码的概念、原理及其在数据压缩中的应用。
相关教材章节:第十四章 数据结构与算法 §5 哈夫曼编码2. 哈夫曼树的构建:讲解哈夫曼树的构建过程,包括选择、合并及构建哈夫曼树的方法。
相关教材章节:第十四章 数据结构与算法 §5 哈夫曼编码3. 哈夫曼编码与解码:介绍哈夫曼编码方法,以及如何利用哈夫曼树进行数据的编码和解码。
相关教材章节:第十四章 数据结构与算法 §5 哈夫曼编码4. C语言实现哈夫曼编码:教授如何利用C语言编写程序实现哈夫曼树的构建、编码和解码过程。
相关教材章节:第十四章 数据结构与算法 §6 C语言实现哈夫曼编码教学内容安排与进度:第一课时:哈夫曼编码基本原理介绍第二课时:哈夫曼树的构建方法及步骤第三课时:哈夫曼编码与解码方法第四课时:C语言实现哈夫曼编码(上)第五课时:C语言实现哈夫曼编码(下)及实践练习本教学内容旨在保证学生掌握哈夫曼编码相关知识,注重理论与实践相结合,使学生在学习过程中逐步提升编程能力和解决问题的能力。
数据结构课程设计哈夫曼编码译码器
题目一: 哈夫曼编码与译码一、任务设计一个运用哈夫曼算法的编码和译码系统, 反复地显示并解决以下项目, 直到选择退出为止。
规定:1) 将权值数据存放在数据文献(文献名为data.txt, 位于执行程序的当前目录中) ;2) 初始化:键盘输入字符集记录字符权值、自定义26个字符和26个权值、记录文献中一篇英文文章中26个字母, 建立哈夫曼树;3) 编码: 运用建好的哈夫曼树生成哈夫曼编码;4) 输出编码(一方面实现屏幕输出, 然后实现文献输出);5)译码(键盘接受编码进行译码、文献读入编码进行译码);6) 界面优化设计。
二、流程图三、代码分解 //头文献 #include<stdio.h> #include<string.h> #include<stdlib.h> #include <conio.h> #define N 1000 #define M 2*N-1 #define MAXcode 6000 //函数声明void count(CHar &ch,HTNode ht[]);void editHCode(HTNode ht[],HCode hcd[],CHar &ch,int n,char bianma[]); //编码函数void printyima(HTNode ht[],HCode hcd[],int n,char bianma[]); //译码函数 void creatHT(HTNode ht[],int n);字符集记录符集记录权值 权值 至文献“哈夫曼树。
t xt” 菜单1.从键盘输入字符集进行编码2.从文献读入字符集进行编码1.从键盘输入编码进行译码2.从文献读入编码进行译码0.返回上级菜单 0.返回上级菜单void CreateHCode (HTNode ht[],HCode hcd[],int n);void DispHCode(HTNode ht[],HCode hcd[],int n);void input_key(CHar &ch);void input_file(CHar &ch);void input_cw(HTNode ht[]);void bianma1(HTNode ht[],HCode hcd[],CHar &ch,int n,char bianma[]); void bianma2(HTNode ht[],HCode hcd[],CHar &ch,int n,char bianma[]); void yima1(HTNode ht[],HCode hcd[],int n,char bianma[]);void yima2(HTNode ht[],HCode hcd[],int n,char bianma[]);void creat_cw();void bianmacaidan();void yimacaidan();void bianmayima();int caidan();//结构体typedef struct{char data;int parent;int weight;int lchild;int rchild;}HTNode;typedef struct{char cd[N];int start;}HCode;typedef struct{char s[N];int num;}CHar;CHar ch;HTNode ht[M];HCode hcd[N];//主函数int main(){int xh;while(1){system("color 1f"); //操作菜单背景颜色 xh=caidan(); //调用菜单函数switch(xh) //switch语句 {case 1:system("cls");creat_cw();break;case 2:system("cls");creatHT(ht,n);break;case 3:system("cls");CreateHCode(ht,hcd,n);DispHCode(ht,hcd,n);break;case 4:system("cls");bianmayima();break;case 0:system("cls");printf("\n\n\n\n\n\n\n\n\n\t\t\t\t感谢使用本系统!\n\n\n\n\n\n\n \t\t\t");exit(0);default:system("cls");putchar('\a');printf("\n\t\t输入有误, 请重新输入:\n");break;}}return 0;}//菜单函数int caidan() //菜单函数模块//{int xh;printf("\n\n\n");printf("\t\t 欢迎使用哈夫曼编码译码系统\n");printf("\t\t \n");printf("\t\t*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*\n");printf("\t\t*= =*\n");printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*= =*\n");printf("\t\t*= 1.建立字符权值=*\n");printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*= =*\n"); printf("\t\t*= 2.建立并输出哈夫曼树=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*= =*\n"); printf("\t\t*= 3.生成并查看哈夫曼编码=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*= =*\n"); printf("\t\t*= 4.编码与译码=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*= =*\n"); printf("\t\t*= 0.退出系统=*\n"); printf("\t\t*= =*\n"); printf("\t\t*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*\n"); printf("\n\t\t请输入序号进行选择:");scanf("%d", &xh);return xh; //返回从键盘接受的选项}void bianmayima(){int xh;while(1){printf("\n\n\n\n\n");printf("\t\t 编码与译码\n"); printf("\t\t \n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n");printf("\t\t*= 1.编码=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 2.译码=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 0.返回上级菜单=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\n\t\t请输入序号进行选择:");scanf("%d",&xh);switch(xh) //switch语句{case 1:system("cls");bianmacaidan();break;case 2:system("cls");yimacaidan();break;case 0:system("cls");return;default:system("cls");putchar('\a');printf("\n\t\t输入有误, 请重新输入:\n");break;}}}void yimacaidan(){int xh;while(1){printf("\n\n\n\n\n");printf("\t\t 译码\n"); printf("\t\t \n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 1.键盘输入编码进行译码=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 2.文献读入编码进行译码=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 0.返回上级菜单=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\n\t\t请输入序号进行选择:");scanf("%d",&xh);switch(xh) //switch语句{case 1:system("cls");yima1(ht,hcd,n,bianma);break;case 2:system("cls");yima2(ht,hcd,n,bianma);break;case 0:system("cls");return;default:system("cls");putchar('\a');printf("\n\t\t输入有误, 请重新输入:\n");break;}}}void bianmacaidan(){int xh;while(1){printf("\n\n\n\n\n");printf("\t\t 编码\n"); printf("\t\t \n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 1.键盘输入字符集编码=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 2.文献读入文章编码=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 0.返回上级菜单=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\n\t\t请输入序号进行选择:");scanf("%d",&xh);switch(xh) //switch语句{case 1:system("cls");bianma1(ht,hcd,ch,n,bianma);break;case 2:system("cls");bianma2(ht,hcd,ch,n,bianma);break;case 0:system("cls");return;default:system("cls");putchar('\a');printf("\n\t\t输入有误, 请重新输入:\n");break;}}}void creat_cw(){int xh2;while(1){printf("\n\n\n\n\n");printf("\t\t 建立字符权值\n"); printf("\t\t \n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 1.从键盘输入字符集进行记录=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 2.从文献读入字符集记录=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 3.自定义字符权值=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 0.返回上级菜单=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\n\t\t请输入序号进行选择:");scanf("%d",&xh2);switch(xh2) //switch语句{case 1:system("cls");input_key(ch);break;case 2:system("cls");input_file(ch);break;case 3:system("cls");input_cw(ht);break;case 0:system("cls");return;default:system("cls");putchar('\a');printf("\n\t\t输入有误, 请重新输入:\n");break;}}}//建立字符权值模块void input_key(CHar &ch){int i,j=0;char st[N];printf("请输入字符集(以‘#’结束):\n");for(i=0;i<N;i++){scanf("%c",&st[i]);if(st[i]=='#'){st[i]='\0';break;}}strcpy(ch.s,st);count(ch,ht);printf("按任意键返回!");getch();system("cls");return;}void input_file(CHar &ch){int i;FILE*fp;char filename[20];printf("请输入要打开的文献名(*.txt):");scanf("%s",&filename);if((fp=fopen(filename,"r"))==NULL){printf("\n\t\t文献打开失败");return;}for(i=0;!feof(fp);i++){fread(&ch.s[i],sizeof(char),1,fp);}printf("读入成功!\n");printf("文献中的字符集为:%s\n",ch.s);fclose(fp);count(ch,ht);printf("按任意键返回!");getch();system("cls");return;}void input_cw(HTNode ht[]){int i,w,s,j;char a;printf("要输入的字符总个数是?:");scanf("%d",&s);n=s;printf("请输入字符及其权值:\n");for(i=0;i<s;i++){printf("请输入第%d个字母:",i+1);scanf("%s",&a);ht[i].data=a;printf("请输入其权值:");scanf("%d",&w);ht[i].weight=w;}FILE *fp;if((fp=fopen("data.txt","w"))==0){printf("\n\t\t文献打开失败");return;}printf("\n定义权值成功!\n\n");printf("各字符及其权值为:\n\n");fprintf(fp,"各字符及其权值为:\n");printf(" 字符\t权值");fprintf(fp," 字符\t权值");for(j=0;j<i;j++){ printf("\n");fprintf(fp,"\n");printf(" %-8c%-8d",ht[j].data,ht[j].weight);fprintf(fp," %-8c%-8d%",ht[j].data,ht[j].weight); }printf("\n");printf("\n字符权值已输出至文献“data.txt”!");fclose(fp);printf("输入完毕, 按任意键返回!");getch();system("cls");return;}//记录字符权值函数void count(CHar &ch,HTNode ht[]){int i,j,m=0;char c[N];int sum[N]={0};for(i=0;ch.s[i]!='\0';i++){for(j=0;j<m;j++)if(ch.s[i]==c[j]||(c[j]>='a'&&c[j]<='z'&&ch.s[i]+32==c[j])) break;if(j<m)sum[j]++;else{if(ch.s[i]>='A'&&ch.s[i]<='Z')c[j]=ch.s[i]+32;else c[j]=ch.s[i];sum[j]++;m++;}}for(i=0;i<m;i++){ht[i].data=c[i];ht[i].weight=sum[i];}n=m;FILE *fp;if((fp=fopen("data.txt","w"))==0) {printf("\n\t\t文献打开失败"); return;}printf("\n记录权值成功!\n\n"); printf("各字符及其权值为:\n\n"); fprintf(fp,"各字符及其权值为:\n"); printf(" 字符\t权值");fprintf(fp," 字符\t权值");for(j=0;j<m;j++){ printf("\n");fprintf(fp,"\n");printf(" %-8c%-8d",ht[j].data,ht[j].weight);fprintf(fp," %-8c%-8d%",ht[j].data,ht[j].weight);}printf("\n");printf("\n字符权值已输出至文献“data.txt”!");fclose(fp);}//构造哈夫曼树void creatHT(HTNode ht[],int n){FILE *fp;if((fp=fopen("哈夫曼树.txt","w"))==0){printf("\n\t\t文献打开失败");return;}int i,j,k,lnode,rnode;int min1,min2;for (i=0;i<2*n-1;i++)ht[i].parent=ht[i].lchild=ht[i].rchild=-1;for (i=n;i<2*n-1;i++){min1=min2=32767;lnode=rnode=-1;for(k=0;k<=i-1;k++)if(ht[k].parent==-1){if (ht[k].weight<min1){min2=min1;rnode=lnode;min1=ht[k].weight;lnode=k;}else if(ht[k].weight<min2){min2=ht[k].weight;rnode=k;}}ht[lnode].parent=i;ht[rnode].parent=i;ht[i].weight=ht[lnode].weight+ht[rnode].weight;ht[i].lchild=lnode;ht[i].rchild=rnode;}printf("建立huffman树成功!\n");printf("输出huffman树:\n");fprintf(fp,"输出huffman树:\n");printf("\t字符\t权值\t父节点\t 左子节点\t右子节点");fprintf(fp,"\t字符\t权值\t父节点\t 左子节点\t右子节点");for(j=1;j<i;j++){ printf("\n");fprintf(fp,"\n");printf("\t %-8c%-8d%-10d%-14d%-10d",ht[j].data,ht[j].weight,ht[j].parent,ht[i]. lchild,ht[j].rchild);fprintf(fp,"\t %-8c%-8d%-10d%-14d%-10d",ht[j].data,ht[j].weight,ht[j].parent,h t[i].lchild,ht[j].rchild);}printf("\n");printf("哈夫曼树已输出至文献“哈夫曼树.txt”!按任意键返回!");fclose(fp);getch();system("cls");return;}//生成哈夫曼编码void CreateHCode (HTNode ht[],HCode hcd[],int n){int i,f,c,j=0;HCode hc;for(i=0;i<n;i++){hc.start=n;c=i;hc.cd[hc.start--]='0';f=ht[i].parent;while(f!=-1){if (ht[f].lchild==c)hc.cd[hc.start--]='0';elsehc.cd[hc.start--]='1';c=f;f=ht[f].parent;}hc.start++;for(j=0;j<hc.start;j++)hc.cd[j]=' ';hcd[i]=hc;}}void DispHCode(HTNode ht[],HCode hcd[],int n) {FILE *fp;if((fp=fopen("哈夫曼编码.txt","w"))==0){printf("\n\t\t文献打开失败");return;}int i,k;int sum=0,m=0,j;printf("输出字符哈夫曼编码:\n"); fputs("输出字符哈夫曼编码:\n",fp); for (i=0;i<n;i++){j=0;printf("%c:\t",ht[i].data);fprintf(fp,"\n%c:\t",ht[i].data);for (k=hcd[i].start;k<=n;k++){printf("%c",hcd[i].cd[k]);j++;fprintf(fp,"%c",hcd[i].cd[k]); }m+=ht[i].weight;sum+=ht[i].weight*j;printf("\n");}printf("\n哈夫曼编码已保存至文献“哈夫曼编码.txt!按任意键返回!”");fclose(fp);getch();system("cls");}//编码函数void bianma1(HTNode ht[],HCode hcd[],CHar &ch,int n,char bianma[]){int i;char str[N];printf("请输入要编码的字符集(以‘#’结束):\n");for(i=0;i<N;i++){scanf("%c",&str[i]);if(str[i]=='#'){str[i]='\0';break;}}strcpy(ch.s,str);ch.num=strlen(str);editHCode(ht,hcd,ch,n,bianma);getch();system("cls");}void bianma2(HTNode ht[],HCode hcd[],CHar &ch,int n,char bianma[]) {int i;FILE*fp;char filename[20];printf("请输入要打开的文献名(*.txt):");scanf("%s",&filename);if((fp=fopen(filename,"r"))==NULL){printf("\n\t\t文献打开失败");return;}for(i=0;!feof(fp);i++){fread(&ch.s[i],sizeof(char),1,fp);}ch.num=strlen(ch.s);printf("\n读入成功!\n");printf("文献中的字符集为:\n%s",ch.s);fclose(fp);editHCode(ht,hcd,ch,n,bianma);system("cls");return;}//译码函数void yima1(HTNode ht[],HCode hcd[],int n,char bianma[]) {int i;char code[MAXcode];printf("请输入编码进行译码(以‘#’结束):\n");for(i=0;i<MAXcode;i++){scanf("%c",&code[i]);if(code[i]=='#'){code[i]='\0';break;}}strcpy(bianma,code);printyima(ht,hcd,n,bianma);printf("\n译码完毕!按任意键返回!");getch();system("cls");return;}void yima2(HTNode ht[],HCode hcd[],int n,char bianma[]) {int i;FILE*fp;char filename[20];printf("请输入要打开的文献名(*.txt):");scanf("%s",&filename);if((fp=fopen(filename,"r"))==NULL){printf("\n\t\t文献打开失败");return;}for(i=0;!feof(fp);i++){fread(&bianma[i],sizeof(char),1,fp);}printf("读入成功!\n");printf("文献中的编码是:%s\n",bianma);printyima(ht,hcd,n,bianma);printf("\n译码完毕!按任意键返回!");getch();system("cls");}四、调试结果主菜单建立字符权值选择2.从文献读入字符进行记录输入测试文献名“cs.txt”输出个字符权值建立哈夫曼树并输出至文献生成哈夫曼编码并保存至文献编码选择2.从文献读入字符集编码编码结果保存至文献译码选择2.从文献读入编码, 读入上一步的编码译码完毕, 返回!退出系统。
数据结构 哈夫曼编码器课程设计报告
数据结构哈夫曼编码器课程设计报告哈夫曼编码器课程设计报告设计目标:本课程设计的目标是实现一个哈夫曼编码器,能够实现对给定文本文件进行压缩和解压缩操作。
通过使用哈夫曼编码,可以使文本文件的大小大幅度减小,从而节约存储空间。
设计原理及实现方法:本设计主要包括以下几个步骤:1、文本文件的读取:首先需要从外部文件中读取待压缩的文本文件,读取过程可以通过使用文件输入流进行操作。
读取的文本内容将用于构建哈夫曼树和编码表。
2、构建哈夫曼树:哈夫曼树是通过给定文本中的字符出现频率来构建的,出现频率更高的字符将拥有更短的编码。
构建哈夫曼树的过程可以通过使用优先队列和二叉树来实现。
3、编码表:在构建哈夫曼树的过程中,每个字符都会有一个唯一的编码。
根据哈夫曼树的特性,左子树的编码为0,右子树的编码为1,根据这个规则可以通过遍历哈夫曼树来编码表。
4、压缩文本文件:在编码表后,可以利用编码表来对文本文件进行压缩操作。
遍历文本文件中的每个字符,通过编码表将字符转换为对应的哈夫曼编码,并将编码存储在一个压缩文件中。
5、解压缩文本文件:解压缩操作是压缩操作的逆过程。
根据编码表将压缩文件中的哈夫曼编码逐个解码为字符,并将解码后的字符写入解压缩文件中。
附件说明:本文档的附件包括以下内容:1、源代码文件:- HuffmanEncoder:java:包含了哈夫曼编码器的主要实现代码。
- Mn:java:包含了测试哈夫曼编码器的主函数。
2、示例文本文件:- input:txt:用于测试的示例文本文件。
法律名词及注释:本文档中涉及的法律名词及注释如下:1、哈夫曼编码:用于数据压缩的一种编码方式,旨在通过减少字符的编码长度来节省存储空间。
2、压缩:将原始文件经过编码转换为较短的文件,从而减小存储空间的占用。
3、解压缩:将压缩文件经过解码转换为原始文件,恢复原始文件的过程。
全文结束。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
湖南科技学院课程设计报告课程名称:数据结构课程设计课程设计题目:哈夫曼编码系:数学与计算科学系专业:信息与计算科学年级、班:信计0901姓名:郭如华学号:200905002145指导教师:牛志毅职称:讲师2011年12月目录1 问题描述 (3)2 基本要求 (3)3 测试数据 (3)4 算法思想 (3)5 模块划分 (3)6 数据结构 (3)7 源程序 (4)8 测试情况 (9)9 设计总结 (9)10参考资料 (9)1 问题描述设计一个哈夫曼编码系统,对文档中的报文进行编码,输出这段报文的哈夫曼编码,并且可以对输入的哈夫曼编码进行译码。
2 基本要求从文档中读取报文(如"what did you do that made you so happy")进行编码输出这段报文的哈夫曼编码。
3 测试数据what did you do that made you so happy4算法思想①:从文件中读取lei.txt并到数组z(保存所有字符的种类),读取data,txt存到数组ch(保存统计频数的一个样本)。
②:对数组z和数组ch进行比较统计出每个字符出现的频数,以频数代替权值,并把权值赋值到ht.weight的的数组中。
③:利用权值创建哈夫曼树。
④:利用哈夫曼树求的哈夫曼编码。
把lei.txt的数据赋值到hcd.ch中,把编好的哈夫曼编码赋值到hcd.code,则hcd这个数组就是一个哈夫曼编码的集合,hcd.ch 对应的下标就是这个字符所对应的哈夫曼编码。
⑤:输入要编码的字符,保存到ch数组,把ch数组的ch[j]元素逐个与hcd[i].ch 比较找出下标i,则hcd[i].code为ch[j]元素的哈夫曼编码。
⑥:输入要译码的哈夫曼编码lcd,逐个与hcd[i].code比较,找出下标i,则hcd[i].ch 为lcd所对应的字符。
5 模块划分①:void inithuffmantree(huffmantree ht);/*初始化哈夫曼树*/②:void tongji(huffmantree ht,huffmancode hcd,char *ch,char *z);/*统计权值*/③:void selectmin(huffmantree ht, int i, int *p1, int *p2);/*选择最小的权值*/④:void createhuffmantree(huffmantree ht) ;/*创建哈夫曼树*/⑤:void huffmancodes(huffmantree ht,huffmancode hcd,char *z) ;/*利用哈夫曼树求哈夫曼编码*/⑥:void bianma(huffmancode hcd);/*对输入的字符进行编码*/⑦:void yima(huffmancode hcd);/*对输入的哈夫曼编码进行译码*/6 数据结构typedef struct{int weight;int lchild,rchild,parent;}htnode;typedef htnode huffmantree[m+1];定义哈夫曼树的结构类型。
typedef struct{char ch;char code[10];} codenode;typedef codenode huffmancode[n+1];定义存储哈夫曼编码的类型。
7 源程序main.cpp#include <iostream>#include <conio.h>#include <stdlib.h>#include"huffman.h"#include<fstream>#include<string.h>using namespace std;int main(){char ch[200];/*用于存储样本*/char z[54];/*用于存储所有字符类别*/huffmantree ht;/*定义一个数组ht,用于存储哈夫曼树*/huffmancode hcd;/*定义一个数组hcd,用于存储哈夫曼编码*/inithuffmantree(ht);/*初始化哈夫曼树*/ifstream infile1("lei.txt");/*lei.txt文件保存了所有字符的总类*/if(!infile1){cout<<"错误:数据文件不能打开!";}for(int i=0; i<54; i++){infile1.get(z[i]);/*把lei.txt的数据读到数组z*/}ifstream infile2("data.txt");/*data.txt文件是统计频数的一个样本,以频数代替权值*/if(!infile2){cout<<"错误:数据文件不能打开!";}for(int i=0; i<200; i++){infile2.get(ch[i]);/*把data.txt数据读到数组ch*/}tongji(ht,ch,z);/*统计权值*/createhuffmantree(ht);/*创建哈夫曼树*/huffmancodes(ht,hcd,z);/*求哈夫曼编码*/bianma(hcd);/*对输入的字符求编码*/cout<<endl;yima(hcd);/*对输入的编码求译码*/}huffman.h#ifndef HUFFMAN_H_INCLUDED#define HUFFMAN_H_INCLUDED#define n 53#define m 2*n-1typedef struct{int weight;int lchild,rchild,parent;}htnode;typedef htnode huffmantree[m+1];/*定义数组存储哈夫曼树*/typedef struct{char ch;char code[10];} codenode;typedef codenode huffmancode[n+1];/*定义数组存储哈夫曼编码*/void inithuffmantree(huffmantree ht);/*初始化哈夫曼树*/void tongji(huffmantree ht,char *ch,char *z);/*统计权值*/void selectmin(huffmantree ht, int i, int *p1, int *p2);/*选择最小的权值*/ void createhuffmantree(huffmantree ht) ;/*创建哈夫曼树*/void huffmancodes(huffmantree ht,huffmancode hcd,char *z) ;/*利用哈夫曼树求哈夫曼编码*/void bianma(huffmancode hcd);/*对输入的字符进行编码*/void yima(huffmancode hcd);/*对输入的哈夫曼编码进行译码*/#endif // HUFFMAN_H_INCLUDEDhuffman.cpp#include<stdio.h>#include<stdlib.h>#include<string.h>#include<conio.h>#include<iostream>#include "huffman.h"using namespace std;void inithuffmantree(huffmantree ht)/*初始化哈夫曼树*/{for(int i=1; i<=m; i++){ht[i].weight=0;ht[i].lchild=0;ht[i].rchild=0;ht[i].parent=0;}}对传入函数的ht进行初始化。
void tongji(huffmantree ht,huffmancode hcd,char *ch,char *z)/*统计权值*/{int l;l=strlen(ch);for(int i=1; i<54; i++)for(int j=1; j<l; j++)if(z[i]==ch[j])ht[i].weight++;}数组ch是从文件data.txt中读取的数据,数组z是从lei.txt中读取的文件,把数组ch与数组z对比,统计每个字符出现的频数,存到ht.weight数组中。
void selectmin(huffmantree ht, int i, int *p1, int *p2)/*创建哈夫曼树*/{int j,min1,min2; /* min1,min2分别是最小权值和次小权值*/min1=min2=1;*p1=*p2=0;for(j=1; j<=i; j++){if(ht[j].parent==0)if(ht[j].weight<min1||min1==1){if(min1!=1){min2=min1;*p2=*p1;}min1=ht[j].weight;*p1=j;}else if(ht[j].weight<min2||min2==1){min2=ht[j].weight;*p2=j;}}}在ht[1..i]中选两个权值最小的根结点,其序号为*p1和*p2,*p1中放权值最小的根结点的序号,*p2中放权值次小的根结点的序号。
void createhuffmantree(huffmantree ht)/*利用哈夫曼树求哈夫曼编码*/{int i,p1,p2;inithuffmantree(ht);for(i=n+1; i<=m; i++){selectmin(ht,i-1,&p1,&p2);ht[p1].parent=ht[p2].parent=i;ht[i].lchild=p1;ht[i].rchild=p2;ht[i].weight=ht[p1].weight+ht[p2].weight;}}在ht[1..i]中选parents为0且weight最小的的两个结点。
其序号为p1,p2. void huffmancodes(huffmantree ht,huffmancode hcd,char *z)/*根据huffman树ht求huffman编码*/{int c,p,i;char cd[n+1];int start;cd[n]='\0';for(i=1; i<54; i++){hcd[i].ch=z[i];start=n;c=i;while((p=ht[c].parent)!=0){cd[--start]=(ht[p].lchild==c)?'0':'1';c=p;}strcpy(hcd[i].code,&cd[start]);}cout<<endl;}数组z是从lei.txt中读取的文件,并把数组lei的值逐个赋给hcd.ch,把编号的哈夫曼编码赋给hcd.code。