当前位置:文档之家› 哈夫曼压缩算法举例

哈夫曼压缩算法举例

哈夫曼压缩算法举例
哈夫曼压缩算法举例

哈夫曼压缩算法举例

【篇一:哈夫曼压缩算法举例】

简介哈夫曼压缩文件dl结构前一段时间在接触位图的时候被位图结

构触动了,感觉它存储得有条理,于是萌生了为哈夫曼压缩文件定

义一个存储结构,称之为哈夫曼压缩文件dl结构。关键是要统一,

这篇博文用的是一种结构,另一篇用的又是另一种,纷杂的样式会

让初学者发晕,所以统一结构对于学习哈夫曼压缩文件会有很大的

帮助。

dl结构组成部分:

节点个数-用以规定创建哈夫曼树节点个数,以便读入节点域;节点

域-用以创建哈夫曼树和产生字符编码;源文件字符数-在解压的时候

有用;编码长度(以位为单位)-源文件编码的总长度,以位为单位;编码域-存储所有字符编码的存储域。为了便于让你不看文字就能明白,看下图,按着这种结构就相当于有了大概的思路。

哈夫曼解压详解解压的过程就简单很多了,因为一些代码已经在解

压过程当中完成,比如哈夫曼树的建立,我们只要设计压缩和解压

通用的接口,就可以很简单的按照编码域的内容,将编码翻译成原文。

读入节点个数;根据1,读入节点域;创建哈夫曼树;读入编码长度;根据4,读入编码域;写入解压后的文件。

根据编码长度(以bit为单位),可以计算出编码域的大小(以

byte为单位),读入编码域就很方便了。其中翻译部分我给出一部

分代码,根据哈夫曼树,将编码域的01串按位处理,转换为字符。code 1判断最低位是0还是1,从而决定指向left还是right;

code =1,将code右移,方便处理下一位;每当翻译出一个字符,

就要将当前的哈夫曼指针重新指向root,p = hf.getroot()。for(i=0;

i nfilelen-1;) // 特地少处理一个字节 code = *(temp+(nsrcindex));

for(int j=7; j j--) p = (code 1) ? p- right : p- left; if(!p- left !p- right) *(pdest+i) = p- data; p = hf.getroot(); i++; code =1; // 为了处理下

一位,右移一位 nsrcindex ++; code = *(temp+(nsrcindex));

for(int j=0; j noffset; j++) p = (code 1) ? p- right : p- left; if(!p-

left !p- right) *(pdest+i) = p- data; cout p- data endl; p =

hf.getroot(); code =1; // 为了处理下一位,右移一位 }附哈夫曼压缩

算法工程:

本文完。monday, december 26, 2011

【篇二:哈夫曼压缩算法举例】

哈夫曼压缩算法编码是当中最好的方法。它使用预先二进制描述来

替换每个符号,长度由特殊符号出现的频率决定。常见的符号需要

很少的位来表示,而不常见的符号需要很多为来表示。

哈夫曼算法在改变任何符号二进制编码引起少量密集表现方面是最

佳的。然而,它并不处理符号的顺序和重复或序号的序列。

哈夫曼压缩算法之原理

我不打算探究哈夫曼编码的所有实际的细节,但基本的原理是为每

个符号找到新的二进制表示,从而通常符号使用很少的位,不常见

的符号使用较多的位。

简短的说,这个问题的解决方案是为了查找每个符号的通用程度,

我们建立一个未压缩数据的柱状图;通过递归拆分这个柱状图为两部

分来创建一个二叉树,每个递归的一半应该和另一半具有同样的权(权是∑nk =1符号数k, n是分之中符号的数量,符号数k是符号k

出现的次数)

这棵树有两个目的:

1. 编码器使用这棵树来找到每个符号最优的表示方法

2. 使用这棵树唯一的标识在压缩流中每个编码的,其通过在读压缩

数据位的时候自顶向底的遍历树,选择基于数据流中的每个独立位

的分支,一旦一个到达,知道一个完整的编码已经读出来了。

哈夫曼编码器生成哈夫曼树

压缩后的数据流是24位(三个字节),原来是80位(10个字节)。当然,我应该存储哈夫曼树,这样就能够解码出对应的压缩流了,这就使

得该例子中的真正数据流比输入的流数据量大。这是相对较短的数

据上的副作用。对于大数据量来说,上面的哈夫曼树就不占太多比

例了

最终的压缩数据流

解码的时候,从上到下遍历树,为压缩的流选择从左/右分支,每次

碰到一个的时候,就可以将对应的字节写到解压输出流中,然后再

从根开始遍历。

哈夫曼压缩算法之实现

哈夫曼编码器可以在基本压缩库中找到,其是非常直接的实现。

这个实现的基本缺陷是:

1. 慢位流实现

2. 相当慢的解码(比编码慢)

3. 最大的树深度是32(编码器在任何超过32位大小的时候退出)。如

果我不是搞错的话,这是不可能的,除非输出的数据大于232字节。另一方面,这个实现有几个优点:

1. 哈夫曼树以一个紧密的形式每个符号要求12位(对于8位的符号)

的方式存储,这意味着最大的头为384。

2. 编码相当容易理解

哈夫曼编码在数据有噪音的情况(不是有规律的,例如rle)下非常好,这中情况下大多数基于字典方式的编码器都有问题。

以上就是对哈夫曼压缩算法的简单介绍。

另外也有你可以看参考资料

希望对您有帮助参考资料:

【篇三:哈夫曼压缩算法举例】

到文件压缩大家很容易想到的就是rar,zip等我们常见的压缩格式。

然而,还有一种就是大家在学习数据结构最常见到的哈夫曼树的数

据结构,以前还不知道他又什么用,其实他最大的用途就是用来做

压缩,也是一些rar,zip压缩的祖先,称为哈弗曼压缩(什么你不知

道谁是哈弗曼,也不知道哈弗曼压缩,不急等下介绍)。

随着网络与多媒体技术的兴起,人们需要存储和传输的数据越来越多,数据量越来越大,以前带宽有限的传输网络和容量有限的存储

介质难以满足用户的需求。

特别是声音、图像和视频等媒体在人们的日常生活和工作中的地位

日益突出,这个问题越发显得严重和迫切。如今,数据压缩技术早

已是多媒体领域中的关键技术之一。

一、什么是哈弗曼压缩

huffman(哈夫曼)算法在上世纪五十年代初提出来了,它是一种无损

压缩方法,在压缩过程中不会丢失信息熵,而且可以证明huffman

算法在无损压缩算法中是最优的。huffman原理简单,实现起来也

不困难,在现在的主流压缩软件得到了广泛的应用。对应用程序、

重要资料等绝对不允许信息丢失的压缩场合,huffman算法是非常

好的选择。

二、怎么实现哈弗曼压缩

哈夫曼压缩是个无损的压缩算法,一般用来压缩文本和程序文件。

哈夫曼压缩属于可变代码长度算法一族。意思是个体符号(例如,

文本文件中的字符)用一个特定长度的位序列替代。因此,在文件

中出现频率高的符号,使用短的位序列,而那些很少出现的符号,

则用较长的位序列。

故我们得了解几个概念:

1、二叉树:在计算机科学中,二叉树是每个结点最多有两个子树的

有序树。通常子树的根被称作左子树(left subtree)和右子树(right subtree)。

2、哈夫曼编码(huffman coding):是一种编码方式,哈夫曼编码是

可变字长编码(vlc)的一种。uffman于1952年提出一种编码方法,

该方法完全依据字符出现概率来构造异字头的平均长度最短的码字,有时称之为最佳编码,一般就叫作huffman编码。

三、哈夫曼编码生成步骤:

①扫描要压缩的文件,对字符出现的频率进行计算。

②把字符按出现的频率进行排序,组成一个队列。

③把出现频率最低(权值)的两个字符作为叶子节点,它们的权值

之和为根节点组成一棵树。

④把上面叶子节点的两个字符从队列中移除,并把它们组成的根节

点加入到队列。

⑤把队列重新进行排序。重复步骤③④⑤直到队列中只有一个节点

为止。

⑥把这棵树上的根节点定义为0(可自行定义0或1)左边为0,右

边为1。这样就可以得到每个叶子节点的哈夫曼编码了。

既如(a)、(b)、(c)、(d)几个图,就可以将离散型的数据转化为树型

的了。

如果假设树的左边用0表示右边用1表示,则每一个数可以用一个

01串表示出来。

则可以得到对应的编码如下:

1-- 110

2-- 111

3-- 10

4-- 0

每一个01串,既为每一个数字的哈弗曼编码。

为什么能压缩:

压缩的时候当我们遇到了文本中的1、2、3、4几个字符的时候,我

们不用原来的存储,而是转化为用它们的01串来存储不久是能减小

了空间占用了吗。(什么01串不是比原来的字符还多了吗?怎么减少?)大家应该知道的,计算机中我们存储一个int型数据的时候一

般式占用了2^32-1个01位,因为计算机中所有的数据都是最后转化为二进制位去存储的。所以,想想我们的编码不就是只含有0和1嘛,因此我们就直接将编码按照计算机的存储规则用位的方法写入进去就能实现压缩了。

比如:

1这个数字,用整数写进计算机硬盘去存储,占用了2^32-1个二进制位

而如果用它的哈弗曼编码去存储,只有110三个二进制位。

效果显而易见。

开始写程序:

开始些程序之前,必须想好自己的文件存储格式,和存储规则是什么

为了简便,我自定义存储的基本信息,格式如下:

savecode[i].nint型//每一个字节的编码长度i:0~256

byte[]byte数组型//每一个字节的编码savecode[i].node中string 的01串转化而来。

byte[]byte数组型//对文件中每一个byte的重新编码的哈夫曼编码写入。

有了定义好的格式我们的读写就非常的方便了,

创建步骤:

①读入文件中的所有字节:

中衡算法分析与【设计明细】-实验二-哈夫曼编码

昆明理工大学信息工程与自动化学院学生实验报告 (201 —201 学年第一学期) 课程名称:算法设计与分析开课实验室:年月日 一、上机目的及内容 1.上机内容 设需要编码的字符集为{d1, d2, …, dn},它们出现的频率为{w1, w2, …, wn},应用哈夫曼树构造最短的不等长编码方案。 2.上机目的 (1)了解前缀编码的概念,理解数据压缩的基本方法; (2)掌握最优子结构性质的证明方法; (3)掌握贪心法的设计思想并能熟练运用。 二、实验原理及基本技术路线图(方框原理图或程序流程图) (1)证明哈夫曼树满足最优子结构性质; (2)设计贪心算法求解哈夫曼编码方案; (3)设计测试数据,写出程序文档。 数据结构与算法: typedef char *HuffmanCode; //动态分配数组,存储哈夫曼编码 typedef struct { unsigned int weight; //用来存放各个结点的权值 unsigned int parent,LChild,RChild; //指向双亲、孩子结点的指针 } HTNode, *HuffmanTree; //动态分配数组,存储哈夫曼树 程序流程图:

三、所用仪器、材料(设备名称、型号、规格等或使用软件) 1台PC及VISUAL C++6.0软件

四、实验方法、步骤(或:程序代码或操作过程) 程序代码: #include #include #include typedef struct { unsigned int weight; unsigned int parent,LChild,RChild; } HTNode, *HuffmanTree; //动态分配数组,存储哈夫曼树 typedef char *HuffmanCode; //动态分配数组,存储哈夫曼编码 void Select(HuffmanTree *ht,int n,int *s1,int *s2) { int i,min; for(i=1; i<=n; i++) { if((*ht)[i].parent==0) { min=i; break; } } for(i=1; i<=n; i++) { if((*ht)[i].parent==0) { if((*ht)[i].weight<(*ht)[min].weight) min=i; } } *s1=min; for(i=1; i<=n; i++) { if((*ht)[i].parent==0 && i!=(*s1)) { min=i; break; } } for(i=1; i<=n; i++) { if((*ht)[i].parent==0 && i!=(*s1)) { if((*ht)[i].weight<(*ht)[min].weight)

贪心算法构造哈夫曼树

软件02 1311611006 张松彬利用贪心算法构造哈夫曼树及输出对应的哈夫曼编码 问题简述: 两路合并最佳模式的贪心算法主要思想如下: (1)设w={w0,w1,......wn-1}是一组权值,以每个权值作为根结点值,构造n棵只有根的二叉树 (2)选择两根结点权值最小的树,作为左右子树构造一棵新二叉树,新树根的权值是两棵子树根权值之和 (3)重复(2),直到合并成一颗二叉树为 一、实验目的 (1)了解贪心算法和哈夫曼树的定义(2)掌握贪心法的设计思想并能熟练运用(3)设计贪心算法求解哈夫曼树(4)设计测试数据,写出程序文档 二、实验内容 (1)设计二叉树结点数据结构,编程实现对用户输入的一组权值构造哈夫曼树(2)设计函数,先序遍历输出哈夫曼树各结点3)设计函数,按树形输出哈夫曼树 代码: #include #include #include #include typedef struct Node{ //定义树结构 int data; struct Node *leftchild; struct Node *rightchild; }Tree; typedef struct Data{ //定义字符及其对应的频率的结构 int data;//字符对应的频率是随机产生的 char c; }; void Initiate(Tree **root);//初始化节点函数 int getMin(struct Data a[],int n);//得到a中数值(频率)最小的数 void toLength(char s[],int k);//设置有k个空格的串s void set(struct Data a[],struct Data b[]);//初始化a,且将a备份至b char getC(int x,struct Data a[]);//得到a中频率为x对应的字符 void prin(struct Data a[]);//输出初始化后的字符及对应的频率 int n; void main() { //srand((unsigned)time(NULL));

实验三.哈夫曼编码的贪心算法设计

实验四 哈夫曼编码的贪心算法设计(4学时) [实验目的] 1. 根据算法设计需要,掌握哈夫曼编码的二叉树结构表示方法; 2. 编程实现哈夫曼编译码器; 3. 掌握贪心算法的一般设计方法。 实验目的和要求 (1)了解前缀编码的概念,理解数据压缩的基本方法; (2)掌握最优子结构性质的证明方法; (3)掌握贪心法的设计思想并能熟练运用 (4)证明哈夫曼树满足最优子结构性质; (5)设计贪心算法求解哈夫曼编码方案; (6)设计测试数据,写出程序文档。 实验内容 设需要编码的字符集为{d 1, d 2, …, dn },它们出现的频率为 {w 1, w 2, …, wn },应用哈夫曼树构造最短的不等长编码方案。 核心源代码 #include #include #include typedef struct { unsigned int weight; //用来存放各个结点的权值 unsigned int parent,LChild,RChild; //指向双亲、孩子结点的指针 } HTNode, *HuffmanTree; //动态分配数组,存储哈夫曼树 typedef char *HuffmanCode; //动态分配数组,存储哈夫曼编码 ∑=j i k k a

//选择两个parent为0,且weight最小的结点s1和s2 void Select(HuffmanTree *ht,int n,int *s1,int *s2) { int i,min; for(i=1; i<=n; i++) { if((*ht)[i].parent==0) { min=i; break; } } for(i=1; i<=n; i++) { if((*ht)[i].parent==0) { if((*ht)[i].weight<(*ht)[min].weight) min=i; } } *s1=min; for(i=1; i<=n; i++)

数据结构哈夫曼树的实现

#include #include #include #include using namespace std; typedef struct { unsigned int weight; unsigned int parent,lchild,rchild,ch; }HTNode,*HuffmanTree; //动态分配数组存储哈夫曼树 typedef char *HuffmanCode; //动态分配数组存储哈夫曼编码表 int m,s1,s2; HuffmanTree HT; void Select(int n){ //选择两个权值最小的结点 int i,j; for(i=1;i<=n;i++){ if(!HT[i].parent){ s1 = i;break; } } for(j=i+1;j<=n;j++){ if(!HT[j].parent){ s2 = j;break; } } for(i=1;i<=n;i++){ if((HT[s1].weight>HT[i].weight)&&(!HT[i].parent)&&(s2!=i)){ s1=i; } } for(j=1;j<=n;j++){ if((HT[s2].weight>HT[j].weight)&&(!HT[j].parent)&&(s1!=j)) s2=j; } } void HuffmanCoding(HuffmanCode HC[], int *w, int n) { // w存放n个字符的权值(均>0),构造哈夫曼树HT,// 并求出n个字符的哈夫曼编码HC int i, j; char *cd; int p; int cdlen; int start; if (n<=1) return;

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

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

《数据结构与算法》课程设计 目录 一、前言 1.摘要 2.《数据结构与算法》课程设计任务书 二、实验目的 三、题目--赫夫曼编码/译码器 1.问题描述 2.基本要求 3.测试要求 4.实现提示 四、需求分析--具体要求 五、概要设计 六、程序说明 七、详细设计 八、实验心得与体会

前言 1.摘要 随着计算机的普遍应用与日益发展,其应用早已不局限于简单的数值运算,而涉及到问题的分析、数据结构框架的设计以及设计最短路线等复杂的非数值处理和操作。算法与数据结构的学习就是为以后利用计算机资源高效地开发非数值处理的计算机程序打下坚实的理论、方法和技术基础。 算法与数据结构旨在分析研究计算机加工的数据对象的特性,以便选择适当的数据结构和存储结构,从而使建立在其上的解决问题的算法达到最优。 数据结构是在整个计算机科学与技术领域上广泛被使用的术语。它用来反映一个数据的内部构成,即一个数据由那些成分数据构成,以什么方式构成,呈什么结构。数据结构有逻辑上的数据结构和物理上的数据结构之分。逻辑上的数据结构反映成分数据之间的逻辑关系,而物理上的数据结构反映成分数据在计算机内部的存储安排。数据结构是数据存在的形式。 《数据结构》主要介绍一些最常用的数据结构,阐明各种数据结构内在的逻辑关系,讨论其在计算机中的存储表示,以及在其上进行各种运算时的实现算法,并对算法的效率进行简单的分析和讨论。数据结构是介于数学、计算机软件和计算机硬件之间的一门计算机专业的核心课程,它是计算机程序设计、数据库、操作系统、编译原理及人工智能等的重要基础,广泛的应用于信息学、系统工程等各种领域。 学习数据结构是为了将实际问题中所涉及的对象在计算机中表示出来并对它们进行处理。通过课程设计可以提高学生的思维能力,促进学生的综合应用能力和专业素质的提高。

哈夫曼编码算法实现完整版

实验三树的应用 一.实验题目: 树的应用——哈夫曼编码 二.实验内容: 利用哈夫曼编码进行通信可以大大提高信道的利用率,缩短信息传输的时间,降低传输成本。根据哈夫曼编码的原理,编写一个程序,在用户输入结点权值的基础上求哈夫曼编码。 要求:从键盘输入若干字符及每个字符出现的频率,将字符出现的频率作为结点的权值,建立哈夫曼树,然后对各个字符进行哈夫曼编码,最后打印输出字符及对应的哈夫曼编码。 三、程序源代码: #include #include #include #include typedef struct{ char data; int weight; int parent,lchild,rchild; }HTNode,*HuffmanTree; typedef char * * HuffmanCode; void Select(HuffmanTree &HT,int n,int m) {HuffmanTree p=HT; int tmp; for(int j=n+1;j<=m;j++) {int tag1,tag2,s1,s2; tag1=tag2=32767; for(int x=1;x<=j-1;x++) { if(p[x].parent==0&&p[x].weights2) //将选出的两个节点中的序号较小的始终赋给s1 { tmp=s1; s1=s2; s2=tmp;} p[s1].parent=j;

哈夫曼编码步骤

哈夫曼编码步骤: 一、对给定的n个权值{W1,W2,W3,...,Wi,...,Wn}构成n棵二叉树的初始集合F= {T1,T2,T3,...,Ti,...,Tn},其中每棵二叉树Ti中只有一个权值为Wi的根结点,它的左右子树均为空。(为方便在计算机上实现算法,一般还要求以Ti的权值Wi的升序排列。) 二、在F中选取两棵根结点权值最小的树作为新构造的二叉树的左右子树,新二叉树的根结点的权值为其左右子树的根结点的权值之和。 三、从F中删除这两棵树,并把这棵新的二叉树同样以升序排列加入到集合F中。 四、重复二和三两步,直到集合F中只有一棵二叉树为止。 /*------------------------------------------------------------------------- * Name: 哈夫曼编码源代码。 * Date: 2011.04.16 * Author: Jeffrey Hill+Jezze(解码部分) * 在Win-TC 下测试通过 * 实现过程:着先通过HuffmanTree() 函数构造哈夫曼树,然后在主函数main()中 * 自底向上开始(也就是从数组序号为零的结点开始)向上层层判断,若在 * 父结点左侧,则置码为0,若在右侧,则置码为1。最后输出生成的编码。*------------------------------------------------------------------------*/ #include #include #define MAXBIT 100 #define MAXVALUE 10000 #define MAXLEAF 30 #define MAXNODE MAXLEAF*2 -1 typedef struct { int bit[MAXBIT]; int start;} HCodeType; /* 编码结构体*/ typedef struct{ int weight; int parent; int lchild; int rchild; int value;} HNodeType; /* 结点结构体*/ /* 构造一颗哈夫曼树*/ void HuffmanTree (HNodeType HuffNode[MAXNODE], int n){ /* i、j:循环变量,m1、m2:构造哈夫曼树不同过程中两个最小权值结点的权值,x1、x2:构造哈夫曼树不同过程中两个最小权值结点在数组中的序号。*/ int i, j, m1, m2, x1, x2; /* 初始化存放哈夫曼树数组HuffNode[] 中的结点*/ for (i=0; i<2*n-1; i++)

哈夫曼树的建立与操作

实验六哈夫曼树的建立与操作 一、实验要求和实验内容 1、输入哈夫曼树叶子结点(信息和权值) 2、由叶子结点生成哈夫曼树内部结点 3、生成叶子结点的哈夫曼编码 4、显示哈夫曼树结点顺序表 二、详细代码(内包含了详细的注释): #include using namespace std; typedef char Elemtype; struct element { int weight; Elemtype date; element* lchild,*rchild; }; class HuffmanTree { public: HuffmanTree()//构造函数 { cout<<"请输入二叉树的个数"<>count; element *s=new element[count];//s为指向数组的指针,保存指向数组的地址 for(int i=0;i>s[i].weight;

cout<<"输入第"<>s[i].date; s[i].lchild=NULL; s[i].rchild=NULL; }//以上为初始化每一个结点 element * *m=new element*[count];//m为指向数组成员的地址的指针,保存【指向数组成员地址的指针】的地址 for(int i=0;iweightweight; return1=i; } } for(int i=0;iweightweight>a) { b=m[i]->weight; return2=i; } } q=new element;//构建一棵新树 q->weight=m[return1]->weight+m[return2]->weight; q->lchild=m[return1]; q->rchild=m[return2]; m[return1]=q; m[return2]=NULL; //用新树替换原来的两子树,并置空一个数 } boot=q;//把最后取得的哈夫曼树的头结点即q赋值给boot

哈夫曼树建立、哈夫曼编码算法的实现

#include /*2009.10.25白鹿原*/ #include /*哈夫曼树建立、哈夫曼编码算法的实现*/ #include typedef char* HuffmanCode;/*动态分配数组,存储哈夫曼编码*/ typedef struct { unsigned int weight ; /* 用来存放各个结点的权值*/ unsigned int parent, LChild,RChild ; /*指向双亲、孩子结点的指针*/ }HTNode, * HuffmanTree; /*动态分配数组,存储哈夫曼树*/ void select(HuffmanTree *ht,int n, int *s1, int *s2) { int i; int min; for(i=1; i<=n; i++) { if((*ht)[i].parent == 0) { min = i; i = n+1; } } for(i=1; i<=n; i++) { if((*ht)[i].parent == 0) { if((*ht)[i].weight < (*ht)[min].weight) min = i; } } *s1 = min; for(i=1; i<=n; i++) { if((*ht)[i].parent == 0 && i!=(*s1)) { min = i; i = n+1; } } for(i=1; i<=n; i++) { if((*ht)[i].parent == 0 && i!=(*s1)) {

if((*ht)[i].weight < (*ht)[min].weight) min = i; } } *s2 = min; } void CrtHuffmanTree(HuffmanTree *ht , int *w, int n) { /* w存放已知的n个权值,构造哈夫曼树ht */ int m,i; int s1,s2; m=2*n-1; *ht=(HuffmanTree)malloc((m+1)*sizeof(HTNode)); /*0号单元未使用*/ for(i=1;i<=n;i++) {/*1-n号放叶子结点,初始化*/ (*ht)[i].weight = w[i]; (*ht)[i].LChild = 0; (*ht)[i].parent = 0; (*ht)[i].RChild = 0; } for(i=n+1;i<=m;i++) { (*ht)[i].weight = 0; (*ht)[i].LChild = 0; (*ht)[i].parent = 0; (*ht)[i].RChild = 0; } /*非叶子结点初始化*/ /* ------------初始化完毕!对应算法步骤1---------*/ for(i=n+1;i<=m;i++) /*创建非叶子结点,建哈夫曼树*/ { /*在(*ht)[1]~(*ht)[i-1]的范围内选择两个parent为0且weight最小的结点,其序号分别赋值给s1、s2返回*/ select(ht,i-1,&s1,&s2); (*ht)[s1].parent=i; (*ht)[s2].parent=i; (*ht)[i].LChild=s1; (*ht)[i].RChild=s2; (*ht)[i].weight=(*ht)[s1].weight+(*ht)[s2].weight; } }/*哈夫曼树建立完毕*/ void outputHuffman(HuffmanTree HT, int m) { if(m!=0) {

哈夫曼树 实验报告

计算机科学与技术学院数据结构实验报告 班级2014级计算机1班学号20144138021 姓名张建华成绩 实验项目简单哈夫曼编/译码的设计与实现实验日期2016.1.5 一、实验目的 本实验的目的是进一步理解哈夫曼树的逻辑结构和存储结构,进一步提高使用理论知识指导解决实际问题的能力。 二、实验问题描述 利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码,此实验即设计这样的一个简单编/码系统。系统应该具有如下的几个功能: 1、接收原始数据。 从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树,并将它存于文件hfmtree.dat中。 2、编码。 利用已建好的哈夫曼树(如不在内存,则从文件hfmtree.dat中读入),对文件中的正文进行编码,然后将结果存入文件codefile.dat中。 3、译码。 利用已建好的哈夫曼树将文件codefile.dat中的代码进行译码,结果存入文件textfile.dat中。 4、打印编码规则。 即字符与编码的一一对应关系。 5、打印哈夫曼树, 将已在内存中的哈夫曼树以直观的方式显示在终端上。 三、实验步骤 1、实验问题分析 1、构造哈夫曼树时使用静态链表作为哈夫曼树的存储。 在构造哈夫曼树时,设计一个结构体数组HuffNode保存哈夫曼树中各结点的信息,根据二叉树的性质可知,具有n个叶子结点的哈夫曼树共有2n-1个结点,所以数组HuffNode的大小设置为2n-1,描述结点的数据类型为: Typedef strcut { Int weight;/*结点权值*/ Int parent; Int lchild; Int rchild; }HNodeType; 2、求哈夫曼编码时使用一维结构数组HuffCode作为哈夫曼编码信息的存储。 求哈夫曼编码,实质上就是在已建立的哈夫曼树中,从叶子结点开始,沿结点的双亲链域回退到根结点,没回退一步,就走过了哈夫曼树的一个分支,从而得到一位哈夫曼码值,由于一个字符的哈夫曼编码是从根结点到相应叶子结点所经过的路径上各分支所组成的0、1序列,因此先得到的分支代码为所求编码的低位码,后得到的分支代码位所求编码的高位码,所以设计如下数据类型:

0023算法笔记——【贪心算法】哈夫曼编码问题

0023算法笔记——【贪心算法】哈夫曼编码问题 1、问题描述 哈夫曼编码是广泛地用于数据文件压缩的十分有效的编码方法。其压缩率通常在20%~90%之间。哈夫曼编码算法用字符在文件中出现的频率表来建立一个用0,1串表示各字符的最优表示方式。一个包含100,000个字符的文件,各字符出现频率不同,如下表所示。 有多种方式表示文件中的信息,若用0,1码表示字符的方法,即每个字符用唯一的一个0,1串表示。若采用定长编码表示,则需要3位表示一个字符,整个文件编码需要300,000位;若采用变长编码表示,给频率高的字符较短的编码;频率低的字符较长的编码,达到整体编码减少的目的,则整个文件编码需要(45×1+13×3+12×3+16×3+9×4+5×4)×1000=224,000位,由此可见,变长码比定长码方案好,总码长减小约25%。 前缀码:对每一个字符规定一个0,1串作为其代码,并要求任一字符的代码都不是其他字符代码的前缀。这种编码称为前缀码。编码的前缀性质可以使译码方法非常简单;例如001011101可以唯一的分解为0,0,101,1101,因而其译码为aabe。

译码过程需要方便的取出编码的前缀,因此需要表示前缀码的合适的数据结构。为此,可以用二叉树作为前缀码的数据结构:树叶表示给定字符;从树根到树叶的路径当作该字符的前缀码;代码中每一位的0或1分别作为指示某节点到左儿子或右儿子的“路标”。 从上图可以看出,表示最优前缀码的二叉树总是一棵完全二叉树,即树中任意节点都有2个儿子。图a表示定长编码方案不是最优的,其编码的二叉树不是一棵完全二叉树。在一般情况下,若C是编码字符集,表示其最优前缀码的二叉树中恰有|C|个叶子。每个叶子对应于字符集中的一个字符,该二叉树有|C|-1个内部节点。 给定编码字符集C及频率分布f,即C中任一字符c以频率f(c)在数据文件中出现。C的一个前缀码编码方案对应于一棵二叉树T。字符c在树T中的深度记为d T(c)。d T(c)也是字符c的前缀码长。则平均码长定义为:

构建哈夫曼树及输出哈夫曼代码及算法思想

哈夫曼树描述文档 一、思路 通过一个argv[]数组存储从test文件中读取字母,然后利用ascal 码循环计算每个字母的权值,利用weight[]是否为零,确定叶子节点,节点个数为count,传入到构建哈夫曼树的子程序中,然后利用cd[]数组存储每一个叶子节点的哈夫曼代码.输出代码时,通过与argv[]数组的比对,扫描ht数组,进而读出所有的数据。 二、截图 三、代码 #include #include #include typedefstruct { char data; int weight; int parent; intlchild;

intrchild; }HTNode; typedefstruct { char cd[50]; int start; }HCode; using namespace std; int enter(char argv[])//进行读入操作 { fstream in; ofstream out; char c; int number=0;//字母个数置为0 in.open("test.txt",ios::in); //打开文件test.txt out.open ("code.txt",ios::trunc); //打开文件code.txt,如果不存在就新建一个,如果存在就清空 if(!in.eof()) in>>c; //从test.txt中读取一个字符存入c printf("原文本是:\n"); while(! in.eof()){ //文件不为空,循环读取一个字符 cout<>c; //从test.txt中读取一个字符存入c } argv[number]='\0'; printf("\n"); in.close; out.close; //使用完关闭文件 return(number);//返回叶子节点数目 } voidCreateHT(HTNodeht[],int n) { inti,j,k,lnode,rnode; double 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=32167; lnode=rnode=-1; for(k=0;k<=i-1;k++) if(ht[k].parent==-1) {

哈夫曼编码_贪心算法

淮海工学院计算机工程学院实验报告书 课程名:《算法分析与设计》 题目:实验3 贪心算法 哈夫曼编码 班级:软件102班 学号:11003215 姓名:鹿迅

实验3 贪心算法 实验目的和要求 (1)了解前缀编码的概念,理解数据压缩的基本方法; (2)掌握最优子结构性质的证明方法; (3)掌握贪心法的设计思想并能熟练运用 (4)证明哈夫曼树满足最优子结构性质; (5)设计贪心算法求解哈夫曼编码方案; (6)设计测试数据,写出程序文档。 实验内容 设需要编码的字符集为{d 1, d 2, …, dn },它们出现的频率为 {w 1, w 2, …, wn },应用哈夫曼树构造最短的不等长编码方案。 实验环境 Turbo C 或VC++ 实验学时 2学时,必做实验 数据结构与算法 struct huffman { double weight; //用来存放各个结点的权值 int lchild,rchild,parent; //指向双亲、孩子结点的指针 }; 核心源代码 #include #include using namespace std; struct huffman { double weight; int lchild,rchild,parent; }; static int i1=0,i2=0; int Select(huffman huff[],int i) { ∑=j i k k a

int min=11000; int min1; for(int k=0;k

哈夫曼编码的JAVA实现课程设计

哈夫曼编码的JAVA实现课程设计 目录 摘要 (2) 一、问题综述 (2) 二、求解方法介绍 (3) 三、实验步骤及结果分析 (4) 四、程序设计源代码 (5) 参考文献 (8)

摘要 利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本,试用java语言设计一个哈夫曼编码系统。通过本课程设计,应使学生掌握哈夫曼编码的特点、储存方法和基本原理,培养学生利用java语言正确编写程序及调试程序的能力,运用数据结构知识解决实际问题的能力。 关键字:哈夫曼编码JA V A语言类方法 一、问题综述 1 哈夫曼编码的算法思想 哈夫曼编码也称前缀编码,它是根据每个字符出现的频率而进行编码的,要求任一字符的编码都不是其它任意字符编码的前缀且字符编码的总长度为最短。它主要应用于通信及数据的传送以及对信息的压缩处理等方面。哈夫曼编码的基础是依据字符出现的频率值而构造一棵哈夫曼树,从而实现最短的编码表示最常用的数据块或出现频率最高的数据,具体的方法是: 1.1 建立哈夫曼树 把N 个字符出现的频率值作为字符的权值,然后依据下列步骤建立哈夫曼树。 1.1.1 由N 个权值分别作N 棵树的根结点而形成一个森林。 1.1.2 从中选择两棵根值最小的树T1 和T2 组成一棵以结点T 为根结点的增长树,根结点T = T1 + T2 ,即新树的根值为原来两棵树的根值之和,而T1 和T2 分别为增长树的左右子树。 1.1.3 把这棵新树T 加入到森林中,把原来的两棵树T1 和T2 从森林中删除。 1.1.4 重复1.1.2~1.1.3 步,直到合并成一棵树为止。 1.2 生成各字符的哈夫曼编码 在上面形成的哈夫曼树中,各个字符的权值结点都是叶子结点,从叶子结点开始向根搜索,如果是双亲的左分支,则用“0”标记,右分支用“1”标记,从叶子结点到根结点所经过的分支编码“0”、“1”的组合序列就是各字符的哈夫曼编码。 2 构造哈夫曼树的算法 1)对给定的n个权值{W1,W2,W3,...,Wi,...,Wn}构成n棵二叉树的初始集合F={T1,T2,T3,...,Ti,..., Tn},其中每棵二叉树Ti中只有一个权值为Wi的根结点,它的左右子树均为空。 2)在F中选取两棵根结点权值最小的树作为新构造的二叉树的左右子树,新二叉树的根结点的权值为其左右子树的根结点的权值之和。 3)从F中删除这两棵树,并把这棵新的二叉树同样以升序排列加入到集合F 中。

数字图像实验 哈夫曼编码的方法和实现1234

实验八哈夫曼编码的方法和实现 一、实验目的 1.掌握哈夫曼编码的基本理论和算法流程; 2. 用VC++6.0编程实现图像的哈夫曼编码。 二、实验内容 1.画出哈夫曼编码的算法流程; 2.用VC++6.0编程实现哈夫曼编码。 三、实验步骤 (1)启动VC++6.0,打开Dip工程。 (2)在菜单栏→insert→resouce→dialog→new,在对话框模版的非控制区点击鼠标右键,在弹出的对话框中选properties,设置为ID:IDD_DLG_Huffman,C标题:哈夫曼编码表。 (3)在弹出的对话框中,添加如下的按钮等控件: (4)在ResourceView栏中→Menu→选IDR_DIPTYPE ,如图 在图像编码菜单栏下空的一栏中,右键鼠标,

在弹出的对话框中选属性properties,在弹出的对话框中,进行如下的设置 (5)右击哈夫曼编码表菜单栏,在建立的类向导中进行如下设置 (6)在DipDoc.cpp中找到void CDipDoc::OnCodeHuffman()添加如下代码void CDipDoc::OnCodeHuffman() { int imgSize; imgSize = m_pDibObject->GetWidth()*m_pDibObject->GetHeight(); //在点处理CPointPro类中创建用来绘制直方图的数据 CPointPro PointOperation(m_pDibObject ); int *pHistogram = PointOperation.GetHistogram(); //生成一个对话框CHistDlg类的实例 CDlgHuffman HuffmanDlg;

哈夫曼编码的方法

1.哈夫曼编码的方法 编码过程如下: (1) 将信源符号按概率递减顺序排列; (2) 把两个最小的概率加起来, 作为新符号的概率; (3) 重复步骤(1) 、(2), 直到概率和达到1 为止; (4) 在每次合并消息时,将被合并的消息赋以1和0或0和1; (5) 寻找从每个信源符号到概率为1处的路径,记录下路径上的1和0; (6) 对每个符号写出"1"、"0"序列(从码数的根到终节点)。 2.哈夫曼编码的特点 ①哈夫曼方法构造出来的码不是唯一的。 原因 ·在给两个分支赋值时, 可以是左支( 或上支) 为0, 也可以是右支( 或下支) 为0, 造成编码的不唯一。 ·当两个消息的概率相等时, 谁前谁后也是随机的, 构造出来的码字就不是唯一的。 ②哈夫曼编码码字字长参差不齐, 因此硬件实现起来不大方便。 ③哈夫曼编码对不同的信源的编码效率是不同的。 ·当信源概率是2 的负幂时, 哈夫曼码的编码效率达到100%; ·当信源概率相等时, 其编码效率最低。 ·只有在概率分布很不均匀时, 哈夫曼编码才会收到显著的效果, 而在信源分布均匀的情况下, 一般不使用哈夫曼编码。 ④对信源进行哈夫曼编码后, 形成了一个哈夫曼编码表。解码时, 必须参照这一哈夫编码表才能正确译码。 ·在信源的存储与传输过程中必须首先存储或传输这一哈夫曼编码表在实际计算压缩效果时, 必须考虑哈夫曼编码表占有的比特数。在某些应用场合, 信源概率服从于某一分布或存在一定规律

使用缺省的哈夫曼编码表有

解:为了进行哈夫曼编码, 先把这组数据由大到小排列, 再按上方法处理 (1)将信源符号按概率递减顺序排列。 (2)首先将概率最小的两个符号的概率相加,合成一个新的数值。 (3)把合成的数值看成是一个新的组合符号概率,重复上述操作,直到剩下最后两个符号。 5.4.2 Shannon-Famo编码 Shannon-Famo(S-F) 编码方法与Huffman 的编码方法略有区别, 但有时也能编 出最佳码。 1.S-F码主要准则 符合即时码条件; 在码字中,1 和0 是独立的, 而且是( 或差不多是)等概率的。 这样的准则一方面能保证无需用间隔区分码字,同时又保证每一位码字几乎有 1位的信息量。 2.S-F码的编码过程 信源符号按概率递减顺序排列; 把符号集分成两个子集, 每个子集的概率和相等或近似相等;

哈夫曼算法及其改进

霍夫曼编码及其改进 在通信中,为了提高信息传输效率,得到或接近信息熵的最小信息率,我们需要解决信源编码的问题。在信源编码中,我们试图让信源编码的平均码长尽可能缩短,减少冗余度,从而提高编码效率。信源编码又分为无失真信源编码和限失真信源编码。 哈夫曼编码(Huffman Coding)是一种无失真编码方式,是可变字长编码(VLC)的一种,由Huffman于1952年提出,该方法完全依据字符出现概率来构造异字头的平均长度最短的码字,有时称之为最佳编码,一般就叫作Huffman编码。哈夫曼编码是一种最优的前缀编码技术。 对于多元独立信源,哈夫曼编码为最佳编码,之所以称之为最佳编码,因为其拥有以下特性:(1) 保证概率大的对应短码,概率小的对应长码,即短码得到充分利用;(2) 每次缩减信源的最后两个码字,总是最后面的一个码元不同,而前面的各个码元相同;(3) 每次缩减信源的最长两个码字有相同的码长。 平均码长n=2×10+8 38+3×7+6+3 38 +4×2 38 +5×1+1 38 =2.68 冗余度 哈夫曼编码是一种非唯一性编码,其编码方式并不唯一。首先,因为对缩减信源最后两个概率小的符号用0和1码的赋予可以是任意的,故可以得到不同的码,但是它们只是码的具体形式不同。其码长n不变,平均码长?也不变,所以没有本质区别。其次,若当缩减信源中合并后的符号概率与其他信源符号概率相同时,从编码方法上说哪个在上面哪个在下面是没有本质区别的,但是得到的码是不相同的对这两种不同的码,它们的码长n不同,但是平均码长?是相同的。 为了克服哈夫曼编码方式存在的问题,提高哈夫曼编码的可用性,我们需要设法降低哈夫曼编码树的存储空间。在数据特定的情况下,我们可以让编码器和解码器使用事先约定的编码树,如此可以消除哈夫曼树生成和传输储存的时间,但是当信源变化,此种方法就不再适用,不具备通用性。

哈夫曼树 哈夫曼编码(先序遍历方法)

#include #include typedef struct Tree { int weight; int left; int right; int parent; }*tree; void CreateHuffman(int n) { int i; int m1,m2,x1,x2; tree Huffman[100]; for(i=0;i< 2*n-1;i++) { Huffman[i] = (tree) malloc(sizeof(struct Tree)); } for(i=0;iweight); } for(i=0;i<2*n-1;i++) { Huffman[i]->parent = -1; Huffman[i]->left = -1; Huffman[i]->right = -1; } int j; for(i=0;i

if( Huffman[j]->weight < m1 && Huffman[j]->parent == -1) { m1 = Huffman[j]->weight ; x1 = j; } } for(j=0;jweight < m2 && Huffman[j]->parent == -1 && x1 != j) { m2 = Huffman[j]->weight ; x2 = j; } } Huffman[x1]->parent = n+i; Huffman[x2]->parent = n+i; Huffman[n+i]->weight =Huffman[x1]->weight + Huffman[x2]->weight ; Huffman[n+i]->left =x1; Huffman[n+i]->right =x2; } for(i=0;i<2*n-1;i++) { printf("%d,", Huffman[i]->weight); } printf("\n"); for(i=0;i<2*n-1;i++) { printf("%d的左结点的下标为%d,右结点的下标为%d\n",Huffman[i]->weight,Huffman[i]->left,Huffman[i]->right); } char s[100]; int x; i--; x = i; int k; k=0; int rs[100];int ls[100]; i=1; tree q[100]; int sum=0;

相关主题
文本预览
相关文档 最新文档