b2科目四模拟试题多少题驾考考爆了怎么补救
b2科目四模拟试题多少题 驾考考爆了怎么补救

数据结构-哈夫曼树编码译码-课程设计-实验报告

电脑杂谈  发布时间:2019-07-11 19:07:24  来源:网络整理

哈夫曼树编码实验报告_编码电子锁设计报告_仪器分析实验预习报告

,构造一棵哈夫曼树,规定哈夫曼树中的左分支代表0,右分支代表1,则从根结点到每个叶结点所经过的路径分支组成的0 和1 的序列便为该结点对应字符编码,我们称之为哈夫曼编码。,wn 作为它们的权值,构造一棵哈夫曼树,规定哈夫曼树中的左分支代表0,右分支代表1,则从根结点到每个叶结点所经过的路径分支组成的0 和1 的序列便为该结点对应字符的编码,我们称之为哈夫曼编码。根据每种字符在电文中出现的次数构造哈夫曼树,将哈夫曼树中每个分支结点的左分支标上0,右分支标上1,把从根结点到每个叶子结点的路径上的标号连接起来,作为叶结点所代表的字符的编码。

哈夫曼树编码实验报告_编码电子锁设计报告_仪器分析实验预习报告

众所周知,在计算机当中,数据的存储和加工都是以字节作为基本单位的,一个西文字符要通过一个字节来表达,而一个汉字就要用两个字节,我们把这种每一个字符都通过相同的字节数来表达的编码形式称为定长编码.以西文为例,例如我们要在计算机当中存储这样的一句话:i am a teacher.就需要15个字节,也就是120个二进制位的数据来实现.与这种定长编码不同的是,哈夫曼编码是一种变长编码.它根据字符出现的概率来构造平均长度最短的编码.换句话说如果一个字符在一段文档当中出现的次数多,它的编码就相应的短,如果一个字符在一段文档当中出现的次数少,它的编码就相应的长.当编码中,各码字的长度严格按照对应符号出现的概率大小进行逆序排列时,则编码的平均长度是最小的.这就是哈夫曼编码实现数据压缩的基本原理.要想得到一段数据的哈夫曼编码,需要用到三个步骤:第一步:扫描需编码的数据,统计原数据中各字符出现的概率.第二步:利用得到的概率值创建哈夫曼树.第三步:对哈夫曼树进行编码,并把编码后得到的码字存储起来.因为定长编码已经用相同的位数这个条件保证了任一个字符的编码都不会成为其它编码的前缀,所以这种情况只会出现在变长编码当中,要想避免这种情况,我们就必须用一个条件来制约定长编码,这个条件就是要想成为压缩编码,变长编码就必须是前缀编码.什么是前缀编码呢。有了字符集的哈夫曼编码表之后,对数据文件的编码过程是:依次读人文件中的字符c,在哈夫曼编码表h中找到此字符,若h[i].ch=c,则将字符c转换为h[i].bits中存放的编码串。为使不等长编码为前缀编码(即要求一个字符的编码不能是另一个字符编码的前缀),可用字符集中的每个字符作为叶子结点生成一棵编码二叉树,为了获得传送报文的最短长度,可将每个字符的出现频率作为字符结点的权值。

仪器分析实验预习报告_编码电子锁设计报告_哈夫曼树编码实验报告

这张编码表的特殊之处在于,它是根据每一个源字符出现的估算概率而建立起来的(出现概率高的字符使用较短的编码哈夫曼树编码实验报告,反之出现概率低的则使用较长的编码,这便使编码之后的字符串的平均期望长度降低,从而达到无损压缩数据的目的)。利用哈夫曼树求得的用于通信的二进制编码称为哈夫曼编码. 树中,从根到每个叶子节点都有一条路径,对路径上各分支约定指向左子树的分支表示“0”码,指向右子树的分支表示“1”码,取每条路径上的“0”或“1”的序列作为各个叶子节点对应的字符编码,称为哈夫曼编码. 用上图的例子来说:。将每个字符的出现频率作为字符结点的权值赋予叶子结点,每个分支结点的左右分支分别用0和1编码,从树根结点到每个叶子结点的路径上。

仪器分析实验预习报告_编码电子锁设计报告_哈夫曼树编码实验报告

通常我们把数据压缩的过程称为编码, 解压缩的过程称为解码。 电报通信是传递文字的二进制码形式的字符串。 但在信息传递时, 总希望总长度能尽可能短, 即采用最短码。 假设每种字符在电文中出现的次数为 Wi,编码长度为 Li, 电文中有 n 种字符, 则电文编码总长度为∑WiLi。 若将此对应到二叉树上, Wi 为叶结点的权, Li 为根结点到叶结点的路径长度。 那么, ∑WiLi恰好为二叉树上带权路径长度。 因此 , 设计电文总长最短的二进制前缀编码,就是以 n 种字符出现的频率作权, 构造一棵哈夫曼树, 此构造过程称为哈夫曼编码。 设计实现的功能: (1) 哈夫曼树的建立; (2) 哈夫曼编码的生成; (3) 编码文件的译码。2第三章 概要设计 哈夫曼编\译码器的主要功能是先建立哈夫曼树, 然后利用建好的哈夫曼树生成哈夫曼编码后进行译码 。 在数据通信中, 经常需要将传送的文字转换成由二进制字符 0、 1 组成的二进制串, 称之为编码。 构造一棵哈夫曼树, 规定哈夫曼树中的左分之代表 0, 右分支代表 1, 则从根节点到每个叶子节点所经过的路径分支组成的 0 和 1 的序列便为该节点对应字符的编码, 称之为哈夫曼编码。

哈夫曼树编码实验报告_编码电子锁设计报告_仪器分析实验预习报告

最简单的二进制编码方式是等长编码。 若采用不等长编码, 让出现频率高的字符具有较短的编码, 让出现频率低的字符具有较长的编码, 这样可能缩短传送电文的总长度。 哈夫曼树课用于构造使电文的编码总长最短的编码方案。3(1) 其主要流程图如图 1-1 所示。 开始 结束 结点数是否大于 1 将 data 和权值赋给 ht 输出根结点和权值 调用 SELECT 函数 计算根结点函数 双亲结点为两子结点之和 输出两子结点和已构造的结点 是否为根结点? 左子是否为空? 此时编码为 0 I<2*N?I++ 编码为 1 否 否 否 右子是否为空 是 是否 否是 是 是4(2) 设计包含的几个方面: ① 哈夫曼树的建立 哈夫曼树的建立由哈夫曼算法的定义可知, 初始森林中共有 n 棵只含有根结点的二叉树。 算法的第二步是: 将当前森林中的两棵根结点权值最小的二叉树, 合并成一棵新的二叉树; 每合并一次, 森林中就减少一棵树, 产生一个新结点。 显然要进行 n-1 次合并, 所以共产生 n-1 个新结点, 它们都是具有两个孩子的分支结点。 由此可知, 最终求得的哈夫曼树中一共有 2n-1 个结点, 其中 n 个结点是初始森林的 n 个孤立结点。

并且哈夫曼树中没有度数为 1 的分支结点。 我们可以利用一个大小为 2n--1 的一维数组来存储哈夫曼树中的结点。 ② 哈夫曼编码 要求电文的哈夫曼编码, 必须先定义哈夫曼编码类型, 根据设计要求和实际需要定义的类型如下: typedet struct { char ch; // 存放编码的字符 char bits[N+1]; // 存放编码位串 int len; // 编码的长度 }CodeNode; // 编码结构体类型 ③ 代码文件的译码 译码的基本思想是: 读文件中编码, 并与原先生成的哈夫曼编码表比较, 遇到相等时, 即取出其对应的字符存入一个新串中。第四章 详细设计 (1) ①哈夫曼树的存储结构描述为: #define N 50 // 叶子结点数 #define M 2*N-1 // 哈夫曼树中结点总数 typedef struct { int weight; // 叶子结点的权值 int lchild, rchild, parent; // 左右孩子及双亲指针 }HTNode; // 树中结点类型 typedef HTNode HuffmanTree[M+1]; ②哈弗曼树的算法 void CreateHT(HTNode ht[],int n)//调用输入的数组 ht[],和节点数 n {int i,k,lnode,rnode;int min1,min2;5 for (i=0;i<2*n-1;i++)ht[i].parent=ht[i].lchild=ht[i].rchild=-1; //所有结点的相关域置初值-1for (i=n;i<2*n-1;i++)//构造哈夫曼树 {min1=min2=32767;//int 的范围是-32768—32767lnode=rnode=-1;//lnode 和 rnode 记录最小权值的两个结点位置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;//两个最小节点的父节点是 iht[i].weight=ht[lnode].weight+ht[rnode].weight;//两个最小节点的父节点权值为两个最小节点权值之和ht[i].lchild=lnode;ht[i].rchild=rnode;//父节点的左节点和右节点 } } (2) 哈弗曼编码 void CreateHCode(HTNode ht[],HCode hcd[],int n) { int i,f,c; HCode hc; for (i=0;i<n;i++)//根据哈夫曼树求哈夫曼编码 { hc.start=n;c=i; f=ht[i].parent;6 while (f!=-1)//循序直到树根结点结束循环 { if (ht[f].lchild==c)//处理左孩子结点hc.cd[hc.start--]='0'; else//处理右孩子结点hc.cd[hc.start--]='1'; c=f;f=ht[f].parent; } hc.start++;//start 指向哈夫曼编码 hc.cd[]中最开始字符 hcd[i]=hc; } } void DispHCode(HTNode ht[],HCode hcd[],int n)//输出哈夫曼编码的列表 { int i,k; printf(" 输出哈夫曼编码:\n"); for (i=0;i<n;i++)//输出 data 中的所有数据, 即 A-Z { printf("%c:\t",ht[i].data);for (k=hcd[i].start;k<=n;k++)//输出所有 data 中数据的编码 { printf("%c",hcd[i].cd[k]);} printf("\n"); } } void editHCode(HTNode ht[],HCode hcd[],int n) //编码函数 { char string[MAXSIZE];int i,j,k; scanf("%s",string);//把要进行编码的字符串存入 string 数组中 printf("\n 输出编码结果:\n"); for (i=0;string[i]!='#';i++)//#为终止标志 {7 for (j=0;j<n;j++) { if(string[i]==ht[j].data)//循环查找与输入字符相同的编号, 相同的就输出这个字符的编码 {for (k=hcd[j].start;k<=n;k++){printf("%c",hcd[j].cd[k]);}break;//输出完成后跳出当前 for 循环 } } } } (3) 哈弗曼译码 void deHCode(HTNode ht[],HCode hcd[],int n)//译码函数 { char code[MAXSIZE]; int i,j,l,k,m,x; scanf("%s",code);//把要进行译码的字符串存入 code 数组中 while(code[0]!='#') for (i=0;i<n;i++) { m=0;//m 为想同编码个数的计数器for (k=hcd[i].start,j=0;k<=n;k++,j++)//j 为记录所存储这个字符的编码个数 { if(code[j]==hcd[i].cd[k])//当有相同编码时 m 值加 1m++; } if(m==j)//当输入的字符串与所存储的编码字符串个数相等时则输出这个的 data 数据 { printf("%c",ht[i].data); for(x=0;code[x-1]!='#';x++)//把已经使用过的 code 数组里的字符串删除 {8 code[x]=code[x+j]; } } } } (4) 主函数 void main() { int n=26,i; char orz,back,flag=1; char str[]={'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'}; //初始化 int fnum[]={186,64,13,22,32,103,21,15,47,57,1,2,32,20,57,63,15,1,48,51,80,23,8,18,1,16};//初始化 HTNode ht[M];//建立结构体 HCode hcd[N];//建立结构体 for (i=0;i<n;i++)//把初始化的数据存入 ht 结构体中 { ht[i].data=str[i]; ht[i].weight=fnum[i]; } while (flag)//菜单函数, 当 flag 为 0 时跳出循环 (5) 显示部分源程序: { printf("\n"); printf("********************************"); printf("\n** 1---------------显示编码 **"); printf("\n** 2---------------进行编码 **"); printf("\n** 3---------------进行译码 **"); printf("\n** 4---------------退出**\n"); printf("* **********************************"); printf("\n"); printf("请输入选择的编号:"); scanf("%c",&orz); switch(orz) {9case 'a':case 'A':system("cls");//清屏函数CreateHT(ht,n);CreateHCode(ht,hcd,n);DispHCode(ht,hcd,n);printf("\n 按任意键返回...");getch();system("cls");break; case 'b': case 'B':system("cls");printf("请输入要进行编码的字符串(以#结束):\n");editHCode(ht,hcd,n);printf("\n 按任意键返回...");getch();system("cls");break; case 'c': case 'C':system("cls");DispHCode(ht,hcd,n);printf("请输入编码(以#结束):\n");deHCode(ht,hcd,n);printf("\n 按任意键返回...");getch();system("cls");break; case 'd': case 'D':flag=0;break; default:system("cls"); }}}10第五章 调试结果 进入主菜单 选 A 时的显示结果 选择 B 时的显示结果11 选 C 时的显示结果12第六章 心得体会 通过这次课程设计, 让我对一个程序的数据结构有更全面更进一步的认识,根据不同的需求, 采用不同的数据存储方式,不一定要用栈哈夫曼树编码实验报告, 二叉树等高级类型,有时用基本的一维数组, 只要运用得当, 也能达到相同的效果, 甚至更佳, 就如这次的课程设计, 通过用 for 的多重循环, 舍弃多余的循环, 提高了程序的运行效率。

为使不等长编码为前缀编码(即要求一个字符的编码不能是另一个字符编码的前缀),可用字符集中的每个字符作为叶子结点生成一棵编码二叉树,为了获得传送报文的最短长度,可将每个字符的出现频率作为字符结点的权值。为使不等长编码为前缀编码,可用字符集中的每个字符作为叶子结点生成一棵编码二叉树,为了获得传送报文的最短长度,可将每个字符的出现频率作为字符结点的权值赋予该结点上,求出此树的最小带权路径长度就等于求出了传送报文的最短长度。,构造一棵哈夫曼树,规定哈夫曼树中的左分支代表0,右分支代表1,则从根结点到每个叶结点所经过的路径分支组成的0 和1 的序列便为该结点对应字符的编码,我们称之为哈夫曼编码。


本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-112203-1.html

    相关阅读
      发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

      热点图片
      拼命载入中...