Huffman树与Huffman树编码算法

实验七 Huffman树与Huffman树编码算法实验(4学时)* 数学与软件科学学院实验报告

学期:2011至2012第 1 学期 2012年 5 月 12 日

课程名称:数据结构专业:信息与计算科学

班级 2010级5班实验编号:实验七

实验项目Huffman树与Huffman树编码算法实验指导教师 **

姓名:** 学号:201** 实验成绩:

实验名称:Huffman树与Huffman树编码算法实验

实验目的:

掌握Huffman树的编码方法和算法实现。

实验内容:(类C算法的程序实现)

(1) 建立Huffman树编码的表示结构,对给定输入信息集合进行Huffman编码,输出编码结果(必做)

(2) 利用Huffman编码算法实现给定信息串的编码结果(必做)

实验准备:

1) 计算机设备;2) 程序调试环境的准备,如TC环境;3) 实验内容的算法分析与代码设计与分析准备。

实验步骤:

(1)算法思想

对于随机输入的一串字符

<1>统计字符串中各类字符。

<2>统计各类字符在字符串中的个数

<3>创建haffman树。

<4>字符进行huffman编码。

<5>输出字符串的haffman编码。

(2)设计算法的数据结构

1)

/*数据结构*/

typedef struct HTTree{

DataType weight;/*字符的个数*/

int flag;/*标记元素*/

char name;/*字符名字*/

int parents,leftChild,rightChild;/*父亲结点、子节点*/

}HTNode,*HuffmanTree;

(3)算法基本操作和描述

1)统计字符串中各类字符,统计各类字符在字符串中的个数。

*函数*/

int IpChar(char *a,int **a1, char *b)

/*统计字符串中元素的种类*/

int t=0,i=0,h=0,n=0;

while(a[t]!='\0')

{

for(i=0;i

{

if(a[t]==a[i]) break;

}

if(i==t)

{

h++;

b[n]=a[t];/*将元素种类放到静态数组中*/

printf("%c",b[n]);

n++;

}

t++;

}

b[n]='\0';

/* printf("\n%d\n",h);*/

*a1=(int *)malloc((h+1)*sizeof(int));

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

{

(*a1)[i]=0;

}

i=0;t=0;

while(b[i]!='\0')

{

for(t=0;a[t]!='\0';t++)

{

if(b[i]==a[t]) (*a1)[i+1]++;/*统计各类元素在字符串中元素的个数*/ }

i++;

}

/* for(i=1;i<=h;i++)

{

printf("%d ",(*a1)[i]);

}*/

printf("\n\n");

return h;

2)创建haffman树。

void CreatHT(HTNode **p,int n)

{

/*创建Huffman树*/

int i;

int t;

int S1,S2;

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

{

t=Select(p,i,&S1,&S2);/*寻找p中i个数中最小的两个数的序号S1和S2,并返回parents的weight为0的序号,且S1

(*p)[S1].parents=t; (*p)[S2].parents=t;/*将返回第一个w eight为0的序号,作为S1和S2的父节点。S1作为左节点,S2作为右节点*/

(*p)[t].leftChild=S1;(*p)[t].rightChild=S2;

(*p)[t].weight=(*p)[S1].weight+(*p)[S2].weight;/*S1、S2的weight之和作为父节点的weight*/

}

}

3)字符进行huffman编码、输出字符串的haffman编码。

int HTencod(char w[],char h[],HTTree *p,int n)

{

char *cd;

char **HC;

int i=1,a,b,t;

int start=1;

cd=(char *)malloc(n*sizeof(char)); /*存储编码字符串的数组*/

HC=(char **)malloc((n+1)*sizeof(char *));/*存储每个字符的编码数组*/

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

printf("Haffman bianma::\n");

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

{

start=n-1;

for(a=i,b=p[a].parents;b;a=b,b=p[b].parents)/*从根节点开始遍历,找出根结点的父节点,

子节点为父节点的右儿子则编码为‘1’,左二子编码为‘0’*/

{

if(p[b].leftChild==a) cd[--start]='0';

else cd[--start]='1';

}

HC[i]=(char *)malloc((n-start)*sizeof(char));/*为每个字母的编码分配存储空间

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

printf("%c:%s\n",p[i].name,HC[i]);/*输出每一个字母的haffman编码*/

}

printf("\n\noutput Huaffman bianma::\n");

for(i=0;i

{

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

{

if(w[i]==h[t-1])

printf("%s",HC[t]);/*输出haffman编码*/

}

}

return ok;

}

4)原程序代码。

#include "stdio.h"

#include "stdlib.h"

#include "malloc.h"

#include "string.h"

/*宏定义*/

#define ok 1

#define TRUE 1

#define FALSE 0

#define ERROR -1

#define overflow -2

#define max 100

/*替换*/

typedef int Status;

typedef int DataType;

/*数据结构*/

typedef struct HTTree{

DataType weight;

int flag;

char name;

int parents,leftChild,rightChild;

}HTNode,*HuffmanTree;

/*函数*/

int IpChar(char *a,int **a1, char *b)

{

/*统计字符串中元素的种类*/

int t=0,i=0,h=0,n=0;

while(a[t]!='\0')

{

for(i=0;i

{

if(a[t]==a[i]) break;

}

if(i==t)

{

h++;

b[n]=a[t];/*将元素种类放到静态数组中*/

printf("%c",b[n]);

n++;

}

t++;

}

b[n]='\0';

/* printf("\n%d\n",h);*/

*a1=(int *)malloc((h+1)*sizeof(int));

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

{

(*a1)[i]=0;

}

i=0;t=0;

while(b[i]!='\0')

{

for(t=0;a[t]!='\0';t++)

{

if(b[i]==a[t]) (*a1)[i+1]++;/*统计各类元素在字符串中元素的个数*/ }

i++;

}

/* for(i=1;i<=h;i++)

{

printf("%d ",(*a1)[i]);

}*/

printf("\n\n");

}

void InitTree(DataType *a,int n,HTNode **p,char *h)

{

/*初始化Huffman树*/

int i;

*p=(HuffmanTree)malloc((2*n)*sizeof(HTNode));

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

{

if(i<=n) /*将所有1...n的weight赋为a[1...n]*/

{

(*p)[i].weight=a[i];

(*p)[i].flag=0;

(*p)[i].name=h[i-1];

(*p)[i].leftChild=0;

(*p)[i].rightChild=0;

(*p)[i].parents=0;

}

else/*将所有在n...2*n的weight赋为0*/

{

(*p)[i].weight=0;

(*p)[i].flag=0;

(*p)[i].leftChild=0;

(*p)[i].rightChild=0;

(*p)[i].parents=0;

}

}

}

int Select(HTNode **p,int n,int *a,int *b)

{

/*返回线性表中第一个父节点为0的结点,并返回表中flag==0的两个最小的结点且a

int i;

int min1=100,min2=100;

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

{

if((*p)[i].weight

{

min1=(*p)[i].weight;

*a=i;

}

(*p)[(*a)].flag=1;

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

{

if((*p)[i].weight

{

min2=(*p)[i].weight;

*b=i;

}

}

(*p)[(*b)].flag=1;

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

{

if((*p)[i].weight==0)

{

break;

}

}

return i;

}

void CreatHT(HTNode **p,int n)

{

/*创建Huffman树*/

int i;

int t;

int S1,S2;

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

{

t=Select(p,i,&S1,&S2);/*寻找p中i个数中最小的两个数的序号S1和S2,并返回parents的weight为0的序号,且S1

(*p)[S1].parents=t; (*p)[S2].parents=t;/*将返回第一个weight为0的序号,作为S1和S2的父节点。S1作为左节点,S2作为右节点*/

(*p)[t].leftChild=S1;(*p)[t].rightChild=S2;

(*p)[t].weight=(*p)[S1].weight+(*p)[S2].weight;/*S1、S2的weight之和作为父节点的weight*/

}

}

void show(HTTree *p,int n)

{

int i;

printf("Output Huaffman's weight::\n");

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

{

printf("p[%d].weight=%d\n",i,p[i].weight);/*输出每个结点的权值*/

}

printf("\n\n");

}

int HTencod(char w[],char h[],HTTree *p,int n)

{

char *cd;

char **HC;

int i=1,a,b,t;

int start=1;

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

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

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

printf("Haffman bianma::\n");

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

{

start=n-1;

for(a=i,b=p[a].parents;b;a=b,b=p[b].parents)/*从根节点开始遍历,找出根结点的父节点,

子节点为父节点的右儿子则编码为‘1’,左二子编码为‘2’*/

{

if(p[b].leftChild==a) cd[--start]='0';

else cd[--start]='1';

}

HC[i]=(char *)malloc((n-start)*sizeof(char));/*为每个字母的编码分配存储空间*/

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

printf("%c:%s\n",p[i].name,HC[i]);/*输出每一个字母的haffman编码*/

}

printf("\n\noutput Huaffman bianma::\n");

for(i=0;i

{

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

{

if(w[i]==h[t-1])

printf("%s",HC[t]);/*输出haffman编码*/

}

}

return ok;

}

int main(int argc, char* argv[])

{

int *a1;

int n;

HTNode *p;

char b[100],h[50];

printf("Please input data's number char::");

gets(b);

strlen(b);

printf("%d \n",strlen(b));

n=IpChar(b,&a1,h);

InitTree(a1,n,&p,h);

CreatHT(&p,n);

show(p,n);

HTencod(b,h,p,n);

printf("\n\n");

return 0;

}

6)测试实例。

1)统计输入元素的个数及元素种类。

2)建立haffman树后的元素权值。

3)各字符的haffman编码。

4)输入字符串的haffman编码。

(6)进一步改进的分析和讨论。

对于建立haffman树左右儿子以及父亲结点都没有使用指针。可以改用指针。

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

实验三树的应用 一.实验题目: 树的应用——哈夫曼编码 二.实验内容: 利用哈夫曼编码进行通信可以大大提高信道的利用率,缩短信息传输的时间,降低传输成本。根据哈夫曼编码的原理,编写一个程序,在用户输入结点权值的基础上求哈夫曼编码。 要求:从键盘输入若干字符及每个字符出现的频率,将字符出现的频率作为结点的权值,建立哈夫曼树,然后对各个字符进行哈夫曼编码,最后打印输出字符及对应的哈夫曼编码。 三、程序源代码: #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;

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

哈夫曼树描述文档 一、思路 通过一个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) 二、题目 (3) 三、实验目的 (3) 四、实验原理 (3) 五、需求分析 (4) 5.1实验要求 (4) 5.2实验内容 (4) 六、概要设计 (4) 6.1所实现的功能函数 (4) 6.2主函数 (5) 6.3 系统结构图 (6) 七、详细设计和编码 (6) 八、运行结果 (12) 九、总结 (15) 9.1调试分析 (15) 9.2 心得体会 (15) 参考文献 (16)

一、摘要 二、题目 哈夫曼树的编码与译码 三、实验目的 (1)熟悉对哈夫曼的应用以及构造方法,熟悉对树的构造方式的应用; (2)进一步掌握哈夫曼树的含义; (3)掌握哈夫曼树的结构特征,以及各种存储结构的特点以及使用范围; (4)熟练掌握哈夫曼树的建立和哈夫曼编码方法; (5)提高分析问题、解决问题的能力,进一步巩固数据结构各种原理与方法; (6)掌握一种计算机语言,可以进行数据算法的设计。 四、实验原理 哈夫曼(Huffman)编码属于长度可变的编码类,是哈夫曼在1952年提出的一种编码方法,即从下到上的编码方法。同其他码词长度一样,可区别的不同码词的生成是基于不同符号出现的不同概率。生成哈夫曼编码算法基于一种称为“编码树”(coding tree)的技术。算法步骤如下: (1)初始化,根据富豪概率的大小按由大到小顺序对符号进行排序; (2)把概率最小的两个符号组成一个新符号(节点),即新符号的概率等于这两个符号概率之和; (3)重复第(2)步,直到形成一个符号为止(树),其概率最后等于1; (4)从编码树的根开始回溯到原始的符号,并将每一下分支赋值1,上分支赋值0; 译码的过程是分解电文中字符串,从根出发,按字符“0”或者“1”确定找做孩 子或右孩子,直至叶子节点,便求得该子串相应的字符。

哈夫曼编码资料

哈夫曼编码译码系统 一、需求分析 1、程序的基本功能: ①构造哈夫曼树及哈夫曼编码:从终端读入字符集大小n、n个字符以及n个对应的权 值,建立哈夫曼树;利用已将建好的哈弗曼树求每个叶结点的哈夫曼编码,并保存。 ②编码:利用已构造的哈弗曼编码对“明文”文件中的正文进行编码,然后将结果存 入“密文”文件中。 ③译码:将“密文”文件中的0、1代码序列进行译码。 ④打印“密文”文件:将文件以紧凑格式显示在终端上,同时,将此字符形式的编码 保存。 ⑤打印哈夫曼树:将已在内存中的哈夫曼以凹入表形式显示在终端上。 2、输入输出要求: ①从键盘接收字符集大小n、以及n个字符和n个权值; ②构造哈夫曼树:将HFMTree数组中的各个位置的各个域都添上相关的值,并将结构 体数组存入文件HTree.txt中。 ③打印哈夫曼树:从HFMTree数组读取相关的结点信息,以凹入表方式将各个结点画 出来; ④构造哈夫曼编码:先从文件HTree.txt中读入相关的字符信息进行哈夫曼编码,将字 符与其对应的编码存入文件HNode.txt中; ⑤编码:利用已构造的哈夫曼树对文件进行编码,打印结果,并将结果存入新建文件 中; ⑥译码:将密文文件中的内容利用HNode.txt中建立的编码规则进行翻译,打印结果, 并将结果存入新建文件中。 3、测试数据: 输入叶子结点个数为4,权值集合为{1,3,5,7},字符集合为{A,B,C,D},且字符集与权值集合一一对应。 二、概要设计 1、抽象数据类型的定义: ①采用静态链表作为哈夫曼树的存储结构; ②求哈夫曼编码时使用一维数组HCode作为哈夫曼编码信息的存储。 2、主模块的流程及各子模块的主要功能: ①int main() { 主菜单; swich语句结构选择; return 0; } ②in_park() { 输入车牌号; 若停车场已满,停入便道中,否则停入停车场; } ③output()

哈夫曼树编码译码实验报告(DOC)

数据结构课程设计设计题目:哈夫曼树编码译码

目录 第一章需求分析 (1) 第二章设计要求 (1) 第三章概要设计 (2) (1)其主要流程图如图1-1所示。 (3) (2)设计包含的几个方面 (4) 第四章详细设计 (4) (1)①哈夫曼树的存储结构描述为: (4) (2)哈弗曼编码 (5) (3)哈弗曼译码 (7) (4)主函数 (8) (5)显示部分源程序: (8) 第五章调试结果 (10) 第六章心得体会 (12) 第七章参考文献 (12) 附录: (12)

在当今信息爆炸时代,如何采用有效的数据压缩技术节省数据文件的存储空间和计算机网络的传送时间已越来越引起人们的重视,哈夫曼编码正是一种应用广泛且非常有效的数据压缩技术。哈夫曼编码是一种编码方式,以哈夫曼树—即最优二叉树,带权路径长度最小的二叉树,经常应用于数据压缩。哈弗曼编码使用一张特殊的编码表将源字符(例如某文件中的一个符号)进行编码。这张编码表的特殊之处在于,它是根据每一个源字符出现的估算概率而建立起来的(出现概率高的字符使用较短的编码,反之出现概率低的则使用较长的编码,这便使编码之后的字符串的平均期望长度降低,从而达到无损压缩数据的目的)。哈夫曼编码的应用很广泛,利用哈夫曼树求得的用于通信的二进制编码称为哈夫曼编码。树中从根到每个叶子都有一条路径,对路径上的各分支约定:指向左子树的分支表示“0”码,指向右子树的分支表示“1”码,取每条路径上的“0”或“1”的序列作为和各个叶子对应的字符的编码,这就是哈夫曼编码。哈弗曼译码输入字符串可以把它编译成二进制代码,输入二进制代码时可以编译成字符串。 第二章设计要求 对输入的一串电文字符实现哈夫曼编码,再对哈夫曼编码生成的代码串进行译码,输出电文字符串。通常我们把数据压缩的过程称为编码,解压缩的过程称为解码。电报通信是传递文字的二进制码形式的字符串。但在信息传递时,总希望总长度能尽可能短,即采用最短码。假设每种字符在电文中出现的次数为Wi,编码长度为Li,电文中有n种字符,则电文编码总长度为∑WiLi。若将此对应到二叉树上,Wi为叶结点的权,Li为根结点到叶结点的路径长度。那么,∑WiLi 恰好为二叉树上带权路径长度。因此,设计电文总长最短的二进制前缀编码,就是以n种字符出现的频率作权,构造一棵哈夫曼树,此构造过程称为哈夫曼编码。设计实现的功能: (1) 哈夫曼树的建立; (2) 哈夫曼编码的生成; (3) 编码文件的译码。

Huffman编码报告

《数据结构》课程设计上机实习报告 课设题目Huffman编码和解码 班级 学生姓名 学号 指导教师 时间2015.12-2015.1

一、设计目的 1.进一步熟悉C语言开发环境,熟悉用C语言完成一个应用程序的设计过程,掌握有关编辑、调试和整合程序的方法和技巧。 2.通过此设计,了解《数据结构》课程中霍夫曼编码的的有关内容,明确其操作,熟悉其设计,同时学习到有关位向量的内容,对文件掌握加深 二、设计内容 Huffman编码与解码 (必做)(Huffman编码、二叉树) [问题描述] 对一篇英文文章(大于2000个英文字符),统计各字符出现的次 数,实现Huffman编码,以及对编码结果的解码。 [基本要求] (1)输出每个字符出现的次数和编码,其中求最小权值要求用堆实 现。 (2)在Huffman编码后,要将编码表和英文文章编码结果保存到文 件中,编码结果必须是二进制形式,即0 1的信息用比特位表示,不 能用字符’0’和’1’表示。 (3)提供读编码文件生成原文件的功能。 三、数据结构说明 在该程序中我仅仅使用了两个结构体来完成编码,用位域来实现bite流存储:const int MAXSIZE=300;//定义一次分配的Huffman储存单词最大量为500 const int OVERFLOW = 0; const int ERROR = 0; const int LineCountNum=500; typedef struct WordCount {

char Word;//存放字符 int freq; int parent , lchild , rchild;//存放亲子节点位置 int place;//用来保存第一次堆排序后,建立霍夫曼表前的相对位置 char *HuffmanCode;//存放霍夫曼编码 }WordCount , *WC;//存放单词结点的结构体 typedef struct HuffmanTree { WC w; int Number;//存储有多少数据存入 }HuffmanTree , *HTree; typedef struct { unsigned int a:1; }bite;//设置位段,存储一个bite //**************操作函数声明*********** void InitHuffmanTree(HTree &H);//初始化霍夫曼树 void HeapSort(WC &W , int Number , int choice);//堆排序核心函数 void HeapAdjust(WC &W , int down , int up , int choice);//堆排序调整函数,实现两种排序 void HuffmanCoding(HTree &H , WC &HT); //求霍夫曼树和霍夫曼编码表 void ShowHuffmanTree(HTree H);//输出霍夫曼树 void Select(WC &W , int i , int &s1 , int &s2);//选择1-i-1之间最小的两个数,且parent为0,用s1,s2返回 void GetTheDeCode(HTree H);//将编码结果写入函数 void PutTheDeCode(FILE *fp1 , FILE *fp2);//将编码结果解码得到文章 void CountTheWord(HTree &H , FILE *fp);//记录单词权值 void ShowTheEassy(FILE *wp);//展示文章 四、详细设计 1.首先我给出了编码和解码的菜单供其选择 2.在编码功能中,我先通过CountTheWord()函数进行单词权值记录,然后 进入编码功能,值得一提的是,编码时我给堆排序设计了两种排序形式——对权值的排序和对位置的排序,以达到选择两个最小的权值结点的最优时间复杂度的目的,此功能通过switch实现,但要给编码结构体中放置一个place 空间,这也从侧面反映了时间和空间矛盾的地方(值得一提的是,有些编码并不可见且有特殊含义,如换行符,所以将字符放入文件中时,并不对其进行处理,读出是进行顺序读出) 3.编码结束后将编码结果,对应字符分别存放在文件中,然后对整篇文章进行 编码

哈夫曼树的编码和译码

#include"stdafx.h" #include"stdio.h" #include"conio.h" #include #include #include using namespace std; #define maxbit 100 #define Maxvalue 2000//最大权值整数常量#define Maxleaf 100//最大叶子结点数 #define size 300//0、串数组的长度 static int n;//实际的叶子结点数 struct HNodeType { int weight; int parent; int lchild; int rchild; int ceng;//结点相应的层数 char ch;//各结点对应的字符 }; struct HCodeType { int bit[maxbit];//存放编码的数组 int start;//编码在数组中的开始位置}; static HNodeType *HuffNode;//定义静态指针HNodeType *init()//初始化静态链表 { HuffNode=new HNodeType[2*n-1]; for(int i=0;i<2*n-1;i++) { HuffNode[i].weight=0; HuffNode[i].parent=-1; HuffNode[i].lchild=-1; HuffNode[i].rchild=-1; HuffNode[i].ceng=-1; HuffNode[i].ch='0'; } return HuffNode; }

哈夫曼算法及其改进

霍夫曼编码及其改进 在通信中,为了提高信息传输效率,得到或接近信息熵的最小信息率,我们需要解决信源编码的问题。在信源编码中,我们试图让信源编码的平均码长尽可能缩短,减少冗余度,从而提高编码效率。信源编码又分为无失真信源编码和限失真信源编码。 哈夫曼编码(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 #include #define n 6 /* 叶子数目*/ #define m 2*n-1 /* 结点总数*/ #define Maxval 1 /* 最大权值*/ typedef char datatype; typedef struct //定义为结构类型 { float weight; //权值 datatype data; int lchild, rchild, parent; } hufmtree; hufmtree tree[m]; typedef struct { char bits[n]; /* 编码数组位串,其中n为叶子结点数目*/ int start; /* 编码在位串的起始位置*/ datatype data; } codetype; codetype code[n]; HUFFMAN(hufmtree tree[ ]) { int i, j, p1,p2; char ch; float small1,small2,f; for( i=0; i

霍夫曼编码表

附录二 表1. 传真用的修正霍夫曼编码表 构造码 64 11011 0000001111 960 011010100 0000001110011 128 10010 000011001000 1024 011010101 0000001110100 192 010111 000011001001 1088 011010110 0000001110101 256 0110111 000001011011 1152 011010111 0000001110110 320 00110110 000000110011 1216 011011000 0000001110111 384 00110111 000000110100 1280 011011001 0000001010010 448 01100100 000000110101 1344 011011010 0000001010011 512 01100101 0000001101100 1448 011011011 0000001010100 576 01101000 0000001101101 1472 010011000 0000001010101 640 01100111 0000001001010 1536 010011001 0000001011010 704 011001100 0000001001011 1600 010011010 0000001011011 768 011001101 0000001001100 1664 011000 0000001100100 832 011010010 0000001001101 1728 010011011 0000001100101 896 011010011 0000001110010 EOL 000000000001 000000000001 结尾码 游程长度 白游程编码 黑游程编码 游程长度白游程编码 黑游程编码 0 00110101 0000110111 32 000111011 000001101010 1 000111 010 33 00010010 000001101011 2 0111 11 34 00010011 000011010010 3 1000 10 35 00010100 000011010011 4 1011 011 36 00010101 000011010100 5 1100 0011 37 00010110 000011010101 6 1110 0010 38 00010111 000011010110 7 1111 00011 39 00101000 000011010111 8 10011 000101 40 00101001 000001101100 9 10100 000100 41 00101010 000001101101 10 00111 0000100 42 00101011 000011011010 11 01000 0000101 43 00101100 000011011011 12 001000 0000111 44 00101101 000001010100 13 000011 00000100 45 00000100 000001010101 14 110100 00000111 46 00000101 000001010110 15 110101 000011000 47 00001010 000001010111 16 101010 0000010111 48 00001011 000001100100 17 101011 0000011000 49 01010010 000001100101 18 0100111 0000001000 50 01010011 000001010010 19 0001100 00001100111 51 01010100 000001010011 20 0001000 00001101000 52 01010101 000000100100 21 0010111 00001101100 53 00100100 000000110111 22 0000011 00000110111 54 00100101 000000111000 23 0000100 00000101000 55 01011000 000000100111 24 0101000 00000010111 56 01011001 000000101000 25 0101011 00000011000 57 01011010 000001011000 26 0010011 000011001010 58 01011011 000001011001 27 0100100 000011001011 59 01001010 000000101011 28 0011000 000011001100 60 01001011 000000101100 29 00000010 000011001101 61 00110010 000001011010 30 00000011 000001101000 62 00110011 000001100110 31 00011010 000001101001 63 00110100 000001100111 205

哈夫曼算法的实现及应用

摘要:哈夫曼树是带权路径长度(WPL)最小的二叉树,通过对哈夫曼算法的研究,提出一种求取哈夫曼树带权路径长度的计算方法和应用。 关键词:哈夫曼算法、二叉树、WPL、编码 1 引言: 哈夫曼树是一种特殊的二叉树,又称最优二叉树:假设有一组(无序)实数{w1,w2,w3,w4,…,wm},现要构造一棵以wi(i=1,2,3,4…,m)为权的m个外部结点的扩充二叉树,使得带权的外部路径长度WPL最小。满足这一要求的扩充二叉树就称为哈夫曼树或最优二叉树。若l表示从根到第i个外部结点的路径长度,m为外部结点的个数,wi 为第i个外部结点的权值,则有WPL=∑wili(0 #include #define MAXINT 50 #define MAXNUM 50 /* 数组w中最多容纳的元素个数,注意m<=MAXNUM */ #define MAXNODE 100 /* 哈夫曼树中的最大结点数,注意2*m-1

c语言静态三叉链表构造一棵Huffman树并求其编码

课程设计题目: 采用静态三叉链表构造一棵Huffman树并求其编码一课程设计应达到的目的: 数据结构课程设计的目的是,为了让学生在学习《数据结构》课程的基础上深入理解数据结构的基本理论,掌握对数据结构的各种操作 的算法设计方法,增强对基础知识和基本方法的综合运用能力,增强对 算法的理解能力,提高软件设计能力,在实践中培养独立分析问题和解 决问题的作风和能力,进一步深入巩固所学理论知识、使理论与实际相 结合的重要实践环节。本课程设计通过完成一些具有一定难度的程序的 编写、调试、运行工作,掌握面向过程程序设计的基本方法,从而提高 学生分析问题解决问题的能力。 课程设计是教学中很重要的一项实践环节,它可以帮助学生充分理解课堂教学中的内容,对提高学生的实践认识和实际动手能力都有很重 要的实际意义。学生应在规定的时间内,按照课程设计的要求,结合所 学的理论知识,查找相关资料,完成好本次课程设计,提高程序编写的 能力,为将来的实际工作取得一定的经验。 二课程设计题目及要求 采用静态三叉链表构造一棵Huffman树并求其编码 增加了权值的计算和Huffman树的输出并写入code文件

三主函数及分析 it学习网收集https://www.360docs.net/doc/5618680277.html, 主程序代码 Main.cpp #include #include #include"readFile.h" #include"HuffmanTree.h" int main() { char str[1000]; cin>>str; HuffmanTree htree(str); htree.print(); htree.writetoFile(); readFile(htree.getstr1(),htree.gethufcodes(),htree.getleafNum()); return 0; } HuffmanTree.h #include #include #include template struct TriNode { T data; int parent,left,right; }; class HuffmanTree { private: char str[1000]; //输入的字符串

delaunay三角网生长准则及算法

Delaunay 三角网是Voronoi(或称thiessen多边形,V 图)图的伴生图形 ◆Delaunay 三角网的定义: 由一系列相连的但不重叠的三角形的集合, 而且这些 三角形的外接圆不包含这个面域的其他任何点。 ◆Voronoi图的定义: Voronoi图把平面分成N 个区,每一个区包括一个点, 该点所在的区域是距离该点最近的点的集合。 ◆Delaunay三角网的特性: ◆不存在四点共圆; ◆每个三角形对应于一个Voronoi图顶点; ◆每个三角形边对应于一个Voronoi图边; ◆每个结点对应于一个Voronoi图区域; ◆Delaunay图的边界是一个凸壳; ◆三角网中三角形的最小角最大。 空外接圆准则最大最小角准则最短距离和准则 在TIN中,过每个三角形的外接圆均不包含点集的其余任何点在TIN中的两相邻三角形形成 的凸四边形中,这两三角形 中的最小内角一定大于交换 凸四边形对角线后所形成的 两三角形的最小内角 一点到基边的两端的距离 和为最小 Delaunay三角剖分的重要的准则

张角最大准则面积比准则对角线准则 一点到基边的张角为最大三角形内切圆面积与三角形 面积或三角形面积与周长平 方之比最小 两三角形组成的凸四边形 的两条对角线之比。这一 准则的比值限定值,须给 定,即当计算值超过限定 值才进行优化 Delaunay三角剖分的重要的准则 不规则三角网(TIN)的建立 ●三角网生长算法就是从一个“源”开始,逐步形成覆盖整个数据区域的三角网。 ●从生长过程角度,三角网生长算法分为收缩生长算法和扩张生长算法两类。 方法说明方法实例 收缩生长算法先形成整个数据域的数据边界(凸壳), 并以此作为源头,逐步缩小以形成整个三 角网 分割合并算法 逐点插入算法 扩张生长算法从一个三角形开始向外层层扩展,形成覆 盖整个区域的三角网 递归生长算法

霍夫曼编码

霍夫曼编码 霍夫曼编码(Huffman Coding)是一种编码方法,霍夫曼编码是可变字长编码(VLC)的一种。1952年,David A. Huffman在麻省理工攻读博士时所提出一种编码方法,并发表于《一种构建极小多余编码的方法》(A Method for the Construction of Minimum-Redundancy Codes)一文。 该方法完全依据字符出现概率来构造异字头的平均长度最短的 码字,有时称之为最佳编码,一般就叫作Huffman编码。 在计算机数据处理中,霍夫曼编码使用变长编码表对源符号(如文件中的一个字母)进行编码,其中变长编码表是通过一种评估来源符号出现机率的方法得到的,出现机率高的字母使用较短的编码,反之出现机率低的则使用较长的编码,这便使编码之后的字符串的平均长度、期望值降低,从而达到无损压缩数据的目的。1951年,霍夫曼和他 在MIT信息论的同学需要选择是完成学期报告还是期末考试。 导师Robert M. Fano给他们的学期报告的题目是,查找最有效的二进制编码。由于无法证明哪个已有编码是最有效的,霍夫曼放弃对已有编码的研究,转向新的探索,最终发现了基于有序频率二叉树编码的想法,并很快证明了这个方法是最有效的。由于这个算法,学生终于青出于蓝,超过了他那曾经和信息论创立者克劳德·香农共同研究过类似编码的导师。霍夫曼使用自底向上的方法构建二叉树,避免了次优算法Shannon-Fano编码的最大弊端──自顶向下构建树。 霍夫曼(Huffman)编码是一种统计编码。属于无损(lossless)压缩编码。

以霍夫曼树─即最优二叉树,带权路径长度最小的二叉树,经常应用于数据压缩。 ←根据给定数据集中各元素所出现的频率来压缩数据的 一种统计压缩编码方法。这些元素(如字母)出现的次数越 多,其编码的位数就越少。 ←广泛用在JPEG, MPEG, H.2X等各种信息编码标准中。霍夫曼编码的步骤 霍夫曼编码的具体步骤如下: 1)将信源符号的概率按减小的顺序排队。 2)把两个最小的概率相加,并继续这一步骤,始终将较高的概率分支放在上部,直到最后变成概率1。 3)将每对组合的上边一个指定为1,下边一个指定为0(或相反)。4)画出由概率1处到每个信源符号的路径,顺序记下沿路径的0和1,所得就是该符号的霍夫曼码字。 信源熵的定义: 概率空间中每个事件所含有的自信息量的数学期望称信源熵或简称熵(entropy),记为: 例:现有一个由5个不同符号组成的30个符号的字 符串:BABACACADADABBCBABEBEDDABEEEBB 计算 (1) 该字符串的霍夫曼码 (2) 该字符串的熵 (3) 该字符串的平均码长

哈夫曼树及编码综合实验报告

《用哈夫曼编码实现文件压缩》 实验报告 课程名称数据结构B 实验学期 2017 至 2018 学年第一学期学生所在院部计算机学院 年级 2016 专业班级信管B162 学生姓名学号 成绩评定: 1、工作量: A(),B(),C(),D(),F( ) 2、难易度:A(),B(),C(),D(),F( ) 3、答辩情况: 基本操作:A(),B(),C(),D(),F( ) 代码理解:A(),B(),C(),D(),F( ) 4、报告规范度:A(),B(),C(),D(),F( ) 5、学习态度:A(),B(),C(),D(),F( )总评成绩:_________________________________ 指导教师: 兰芸

用哈夫曼编码实现文件压缩 1、了解文件的概念。 2、掌握线性链表的插入、删除等算法。 3、掌握Huffman树的概念及构造方法。 4、掌握二叉树的存储结构及遍历算法。 5、利用Huffman树及Huffman编码,掌握实现文件压缩的一般原理。 微型计算机、Windows 7操作系统、Visual C++6.0软件 输入的字符创建Huffman树,并输出各字符对应的哈夫曼编码。 五.系统设计 输入字符的个数和各个字符以及权值,将每个字符的出现频率作为叶子结点构建Huffman树,规定哈夫曼树的左分支为0,右分支为1,则从根结点到每个叶子结点所经过的分支对应的0和1组成的序列便为该结点对应字符的哈夫曼编码。 流程图如下 1.输入哈夫曼字数及相应权值

相应代码 int main() { HuffmanTree HTree; HuffmanCode HCode; int *w, i; int n,wei; //编码个数及权值 printf("请输入需要哈夫曼编码的字符个数:"); scanf("%d",&n); w=(int*)malloc((n+1)*sizeof(int)); for(i=1; i<=n;i++) { printf("请输入第%d字符的权值:",i); fflush(stdin); scanf("%d",&wei); w[i]=wei; } HuffmanCoding(&HTree,&HCode,w,n); return 1; } 2.输出HT初态(每个字符的权值)

huffman编码的matlab实现

Huffman编码的matlab实现 一、信源编码介绍 为了减少信源输出符号序列中的剩余度、提高符号的平均信息量,对所施行的变换。具体说,就是针对信源输出符号序列的统计特性来寻找某种方法,把信源输出符号序列变换为最短的码字序列,使后者的各码元所载荷的平均信息量最大,同时又能保证无失真地恢复原来的符号序列。 既然信源编码的基本目的是提高码字序列中码元的平均信息量,那么,一切旨在减少剩余度而对信源输出符号序列所施行的变换或处理,都可以在这种意义下归入信源编码的范畴,例如过滤、预测、域变换和数据压缩等。当然,这些都是广义的信源编码。 一般来说,减少信源输出符号序列中的剩余度、提高符号平均信息量的基本途径有两个:①使序列中的各个符号尽可能地互相独立;②使序列中各个符号的出现概率尽可能地相等。前者称为解除相关性,后者称为概率均匀化。 信源编码的一般问题可以表述如下: 信源编码 若某信源的输出为长度等于M的符号序列集合式中符号A为信源符号表,它包含着K个不同的符号,A={ɑk|k=1,…,K},这个信源至多可以输出K M个不同的符号序列。记‖U‖=KM。所谓对这个信源的输出 信源编码 进行编码,就是用一个新的符号表B的符号序列集合V来表示信源输出的符号序列集合U。若V的各个序列的长度等于 N,即式中新的符号表B共含L个符号,B={b l|l=1,…,L}。它总共可以编出L N个不同的码字。类似地,记‖V‖=LN。为了使信源的每个输出符号序列都能分配到一个独特的码字与之对应,至少应满足关系‖V‖=L N≥‖U‖=KM或者N/M≥log K/log L 下面的几个编码定理,提供了解决这个矛盾的方法。它们既能改善信息载荷效率,又能保证码字唯一可译。 离散无记忆信源的定长编码定理 对于任意给定的ε>0,只要满足条件N/M≥(H(U)+ε)/log L 那么,当M足够大时,上述编码几乎没有失真;反之,若这个条件不满足,就不可能实现无失真的编码。式中H(U)是信源输出序列的符号熵。 信源编码 通常,信源的符号熵H(U)

Delaunay三角网表示点和删除算法

0引言 对于静态数据三角化(数据点不能动态插入与删除),有许多D-三角网构建算法[1-5];对于动态的点插入,使用逐点插入的方法进行动态局部更新;对于动态的点删除,使用的方法有两种,一是基于凸耳权值的点删除方法[6-7],二是基于空外接圆准则和凸耳性质的点删除方法[8-9],上述两种方法都是基于凸耳删除的方法,存在难以理解或算法效率差的缺点。本文提出了一种数据结构来存储D-三角网和表现其拓扑关系,对其中的点删除算法进行了改进,可实现D-三角网中数据点的快速删除操作。 1存储结构 对于三角格网的存储结构,本文设计了点、有向边的存储 表示,三角形的信息在有向边的遍历中隐含,其C++实现如下: Class Point2d {double x,y;} Class Edge { Public:Int num;Edge* next;Edge* prev; Point2d*data;Edge (){data =0;} Edge*Sym (){return (num<1)?this+1:this-1;}Edge*Onext (){return next;}Edge*Oprev (){return prev;} void EndPoints (Point2d*or,Point2d*de ){data =or;Sym ()->data =de;} TwinEdge*Tedge (){return (TwinEdge *)(this -num );}}; Class TwinEdge {Private:Edge e [2];Public:TwinEdge (){ e [0].num =0;e [0].next =&(e [0]);e [1].num =1;e [1].next =&(e [1]); 收稿日期:2007-03-01E-mail :mengl@https://www.360docs.net/doc/5618680277.html, 基金项目:国家863高技术研究发展计划基金项目(2002AA114020、2001AA135210);中国科学院知识创新基金项目(20036020)。 作者简介:孟亮(1968-),男,山西临汾人,博士研究生,研究方向为GIS 、计算机图形学;方金云(1968-),男,山东青岛人,博士,副研究员,研究方向为海量空间数据处理关键支撑技术、网格GIS 等;唐志敏(1966-),男,江苏江阴人,研究员,博士生导师,研究方向为计算机系统结构、网络并行处理。 Delaunay 三角网表示和点删除方法 孟 亮,方金云,唐志敏 (中国科学院计算技术研究所,北京100080) 摘 要:对于三角网的表示方法,提出了一种双循环链表结构,这种结构能够方便的表示三角网的边拓扑和面拓扑信息,以及多边形结构。基于这种结构,对三角网点删除算法进行了改进。以前的点删除算法是基于连续的凸耳删除,提出的方法是基于多边形边的构建方法,利用D-三角网的空外接圆属性。与其它方法相比,这种方法具有容易理解,效率高的优点。关键词:Delaunay 三角网;凸耳;点删除;拓扑结构;双循环链表中图法分类号:TP391;P208 文献标识码:A 文章编号:1000-7024(2008)03-0738-03 Delaunay TIN expression and point deletion method MENG Liang, FANG Jin-yun, TANG Zhi-min (Institute of Computing Technology,Chinese Academy of Sciences,Beijing 100080,China ) Abstract :As to representation of triangulated irregular network (TIN ),a dual-circulation linked list structure is proposed,this structure can conveniently express edge and plane topology information of triangulated irregular network,and polygon structure.Based on this structure,improvements are achieved about TIN point deletion algorithm.Previous point deletion algorithm is based on continuous ears deletion,the methods proposed is based on edge construction method of polygon,using Delaunay TIN circumcircle https://www.360docs.net/doc/5618680277.html,pared with other methods,this method has the advantage of easy understanding,higher efficiency. Key words :Delaunay triangulated irregular network;ears;point deletion;topology structure;dual-circulation linked list 2008年2月计算机工程与设计 Feb.2008 第29卷第3期Vol.29 No.3 Computer Engineering and Design

相关文档
最新文档