霍夫曼编码+详细源代码及注释

合集下载

霍夫曼编码的matlab实现(信源编码实验)资料

霍夫曼编码的matlab实现(信源编码实验)资料

霍夫曼编码的m a t l a b 实现(信源编码实验)重庆交通大学信息科学与工程学院综合性设计性实验报告专业班级:通信工程2012级1班学号: 631206040118姓名:王松实验所属课程:信息论与编码实验室(中心):软件与通信实验中心指导教师:黄大荣2015年4月霍夫曼编码的matlab实现一、实验目的和要求。

利用哈夫曼编码进行通信可以大大提高信道的利用率,缩短信息传输的时间,降低传输成本。

本实验用Matlab语言编程实现霍夫曼(Huffman)编码。

二、实验原理。

霍夫曼(Huffman)编码算法是满足前缀条件的平均二进制码长最短的编-源输出符号,而将较短的编码码字分配给较大概率的信源输出。

算法是:在信源符号集合中,首先将两个最小概率的信源输出合并为新的输出,其概率是两个相应输出符号概率之和。

这一过程重复下去,直到只剩下一个合并输出为止,这个最后的合并输出符号的概率为1。

这样就得到了一张树图,从树根开始,将编码符号1 和0 分配在同一节点的任意两分支上,这一分配过程重复直到树叶。

从树根到树叶途经支路上的编码最后就构成了一组异前置码,就是霍夫曼编码输出。

离散无记忆信源:例如U u1u2u3u4u5P(U) = 0.4 0.2 0.2 0.1 0.1通过上表的对信源缩减合并过程,从而完成了对信源的霍夫曼编码。

三、实验步骤分为两步,首先是码树形成过程:对信源概率进行合并形成编码码树。

然后是码树回溯过程:在码树上分配编码码字并最终得到霍夫曼编码。

1、码树形成过程:将信源概率按照从小到大顺序排序并建立相应的位置索引。

然后按上述规则进行信源合并,再对信源进行排序并建立新的位置索引,直到合并结束。

在这一过程中每一次都把排序后的信源概率存入矩阵G中,位置索引存入矩阵Index中。

这样,由排序之后的概率矩阵G以及索引矩阵Index就可以恢复原概率矩阵P了,从而保证了回溯过程能够进行下去。

2、码树回溯过程:在码树上分配编码码字并最终得到Huffman 编码。

c语言实现霍夫曼编码 概述及解释说明

c语言实现霍夫曼编码 概述及解释说明

c语言实现霍夫曼编码概述及解释说明1. 引言1.1 概述本篇长文主要介绍了C语言如何实现霍夫曼编码。

霍夫曼编码是一种广泛应用于信息压缩领域的算法,通过利用字符出现频率的统计信息,能够将常见字符用较短的二进制串来表示,从而实现数据的高效压缩和传输。

文章将详细说明霍夫曼编码的基本原理,以及在C语言中实施该算法所需的步骤和思路。

1.2 文章结构本文按照以下结构来组织内容:第一部分为引言部分,对文章进行概述并介绍文章结构;第二部分将介绍霍夫曼编码的基本原理,包括信息压缩与编码的关系、霍夫曼编码的定义以及构建霍夫曼树的过程;第三部分详细说明了在C语言中实现霍夫曼编码所需的算法思路和步骤,包括文本文件的读取与处理、统计字符频率并构造优先队列、构建霍夫曼树及生成编码表等;第四部分给出了示例代码演示,在这一部分中我们提供了完整的C语言实现代码示例,并解释了样例文件的压缩与解压缩过程;最后一部分是结论与讨论,我们将探讨霍夫曼编码在信息压缩中的应用价值,并对C语言实现霍夫曼编码的工作进行总结和展望。

1.3 目的本文的目的是帮助读者理解霍夫曼编码算法及其在C语言中的实现。

通过阅读本文,读者将能够掌握如何使用C语言来处理文本文件、统计字符频率并构建优先队列、构建霍夫曼树以及生成对应的编码表。

同时,本文还将探讨霍夫曼编码在信息压缩中的应用价值,并对C语言实现霍夫曼编码进行总结和展望。

2. 霍夫曼编码的基本原理2.1 信息压缩与编码霍夫曼编码是一种常用的无损数据压缩算法,通过对不同字符赋予不同的可变长度编码来达到有效压缩数据的目的。

在信息压缩中,我们希望用更少的位数来表示出现频率较高的字符,而用更多的位数来表示出现频率较低的字符,从而减小整个消息占用的存储空间。

2.2 霍夫曼编码的定义霍夫曼编码是一种前缀编码,即没有一个字符是另一个字符编码序列的前缀。

这确保了在解析编码时不会存在歧义。

根据霍夫曼编码规则,出现频率较低的字符使用比较长的二进制串来表示,而出现频率较高的字符则使用较短的二进制串进行表示。

霍夫曼编码

霍夫曼编码

摘要内容:霍夫曼编码是可变字长编码(VLC)的一种。

在变字长编码中,如果码字长度严格按照对应符号出现的概率大小逆序排列,则其平均码字长度为最小。

霍夫曼编码用于数据的无损压缩,通过构建霍夫曼树,然后建立起一张特殊的霍夫曼编码表将元字符进行编码。

它是根据每一个源字符出现的估算概率,即权重而建立起来的,就是出现概率高的字符使用较短的编码,反之出现概率低的则使用较长的编码,这便使编码之后的字符串的平均期望长度降低,从而达到无损压缩数据的目的,同时保持编码的惟一可解性。

霍夫曼编码并不是唯一的,当权重相同的时候,不同的编码方式会产生不同的码。

关键词:霍夫曼编码霍夫曼树霍夫曼编码表摘要目录任务书一 ........................................... 错误!未定义书签。

摘要 . 0目录 (1)一、课程设计内容 ................................... 错误!未定义书签。

二、课程设计目的 ................................... 错误!未定义书签。

三、环境需求 ....................................... 错误!未定义书签。

四、Huffman 编码的基本原理......................... 错误!未定义书签。

五、问题回答 (9)六、实验结果 (10)七、实验心得体会 (11)八、附录(参考文献、源程序) (11)一、课程设计内容利用 C 语言实现完整的Huffman 数据压缩编码和解码。

二、课程设计目的(1) 加深对数据结构相关算法的理解,综合运用C 语言编写信源编码程序。

(2) 理解Huffman 编码和解码的特点,掌握数据压缩的基本原理,并能够用C 语言编程实现。

(3) 掌握结构化分析,设计与编程方法,学会编写动态链接库程序。

三、环境需求Visual C++ 6.0 以上编程环境。

Huffman编码完整程序

Huffman编码完整程序

本文档包含huffman编码,解码,译码,生成huffman树的所有程序。

实验代码为://..................huffmantree..............................//typedef struct{int weight;int parent;int left;int right;}HuffmanTree;typedef char *HuffmanCode;void SelectNode(HuffmanTree *ht,int n,int *bt1,int *bt2){HuffmanTree *ht1,*ht2,*t;ht1=ht2=NULL;for(int i=1;i<=n;i++){if(! ht[i].parent){if(ht1==NULL){ht1=ht+i;continue;}if(ht2==NULL){ht2=ht+i;if(ht1->weight > ht2->weight){t=ht2;ht2=ht1;ht1=t;}continue;}if(ht1 && ht2){if(ht[i].weight <= ht1->weight){ht2=ht1;ht1=ht+1;}else if(ht[i].weight < ht2->weight){ht2=ht+i;}}}}if(ht1 > ht2){*bt2=ht1-ht;*bt1=ht2-ht;}else{*bt1=ht1-ht;*bt2=ht2-ht;}}void CreatTree(HuffmanTree *ht,int n,int *w) {int i,m=2*n-1;int bt1,bt2;if(n<=1) return;for(i=1;i<=n;i++){ht[i].weight=w[i-1];ht[i].parent=0;ht[i].left=0;ht[i].right=0;}for(;i<=m;++i){ht[i].weight=0;ht[i].parent=0;ht[i].left=0;ht[i].right=0;}for(i=n+1;i<=m;++i){SelectNode(ht,i-1,&bt1,&bt2);ht[bt1].parent=i;ht[bt2].parent=i;ht[i].left=bt1;ht[i].right=bt2;ht[i].weight=ht[bt1].weight+ht[bt2].weight;}}void HuffmanCoding(HuffmanTree *ht,int n,HuffmanCode *hc) {char *cd;int start,i,current,parent;cd=(char *)malloc(sizeof(char)*n);cd[n-1]='\0';for(i=1;i<=n;i++){start=n-1;current=i;parent=ht[current].parent;while(parent){if(current==ht[parent].left)cd[--start]='0';elsecd[--start]='1';current=parent;parent=ht[parent].parent;}hc[i-1]=(char *)malloc(sizeof(char)*(n-start));strcpy(hc[i-1],&cd[start]);}free(cd);}void Encode(HuffmanCode *hc,char *alphabet,char *str,char *code) {int len=0,i=0,j;code[0]='\0';while(str[i]){j=0;while(alphabet[j] != str[i])j++;strcpy(code+len,hc[j]);len=len+strlen(hc[j]);i++;}code[len]='\0';}void Decode(HuffmanTree *ht,int m,char *code,char *alphbet,char *decode) {int position=0,i,j=0;m=2*m-1;while(code[position]){for(i=m;ht[i].left && ht[i].right;position++){if(code[position]=='0')i=ht[i].left;elsei=ht[i].right;}decode[j]=alphbet[i-1];j++;}decode[j]='\0';}主函数为:int main(){int i,n=4,m;char test[]="DBDBDABDCDADBDADBDADACDBDBD";char code[100],code1[100];char alphabet[]={'A','B','C','D'};int w[]={5,7,2,13};HuffmanTree *ht;HuffmanCode *hc;m=2*n-1;ht=(HuffmanTree *)malloc((m+1)*sizeof(HuffmanTree));if(! ht){cout<<"failed !"<<endl;exit(0);}hc=(HuffmanCode *)malloc(n*sizeof(char *));if(! hc){cout<<"failed !"<<endl;exit(0);}CreatTree(ht,n,w);HuffmanCoding(ht,n,hc);for(i=1;i<=n;i++)cout<<"alpabet:"<<alphabet[i-1]<<" weight:"<<ht[i].weight<<" code:"<<hc[i-1]<<endl;Encode(hc,alphabet,test,code);cout<<"the string is:"<<alphabet<<endl;cout<<"now encode is:"<<code<<endl;Decode(ht,n,code,alphabet,code1);cout<<endl<<code<<endl;cout<<code1<<endl;return 0;}。

霍夫曼编码

霍夫曼编码

#include <stdio.h>#include <stdlib.h>#include <string.h>#define MAXLEN 100typedef struct{int weight;int lchild;int rchild;int parent;char key;}htnode;typedef htnode hfmt[MAXLEN];int n;void inithfmt(hfmt t)//对结构体进行初始化{int i;printf("\n");printf("------------------------------------------------------------------\n");printf("******************************输入区******************************\n");printf("\n请输入n=");scanf("%d",&n);getchar();for(i=0;i<2*n-1;i++)//对结构体进行初始化{t[i].weight=0;t[i].lchild=-1;t[i].rchild=-1;t[i].parent=-1;}printf("\n");}void inputweight(hfmt t)//输入函数{int w;//w表示权值int i;char k;//k表示获取的字符for(i=0;i<n;i++){printf("请输入第%d个字符:",i+1);scanf("%c",&k);getchar();t[i].key=k;printf("请输入第%d个字符的权值:",i+1);scanf("%d",&w);getchar();t[i].weight=w;printf("\n");}}void selectmin(hfmt t,int i,int *p1,int *p2)//选中两个权值最小的函数{long min1=999999;long min2=999999;int j;for(j=0;j<=i;j++)//选择最小权值字符的下标返回if(t[j].parent==-1)if(min1>t[j].weight){min1=t[j].weight;*p1=j;}for(j=0;j<=i;j++)//选择次小权值字符的下标还回if(t[j].parent==-1)if(min2>t[j].weight && j!=(*p1))//注意 j!=(*p1)) {min2=t[j].weight;*p2=j;}}void creathfmt(hfmt t)//创建哈夫曼树的函数{int i,p1,p2;inithfmt(t);inputweight(t);for(i=n;i<2*n-1;i++){selectmin(t,i-1,&p1,&p2);t[p1].parent=i;t[p2].parent=i;t[i].lchild=p1;t[i].rchild=p2;t[i].weight=t[p1].weight+t[p2].weight;}}void printhfmt(hfmt t)//打印哈夫曼树{int i;printf("------------------------------------------------------------------\n");printf("**********************哈夫曼编数结构:*****************************\n");printf("\t\t权重\t父母\t左孩子\t右孩子\t字符\t");for(i=0;i<2*n-1;i++){printf("\n");printf("\t\t%d\t%d\t%d\t%d\t%c",t[i].weight,t[i].parent,t[i].lchild,t [i].rchild,t[i].key);}printf("\n------------------------------------------------------------------\n");printf("\n\n");}void hfmtpath(hfmt t,int i,int j)//编码的重要哈夫曼树路径递归算法{int a,b;a=i;b=j=t[i].parent;if(t[j].parent!=-1){i=j;hfmtpath(t,i,j);}if(t[b].lchild==a)printf("0");elseprintf("1");}void phfmnode(hfmt t)//对字符进行初始编码{int i,j,a;printf("\n------------------------------------------------------------------\n");printf("**************************哈夫曼编码******************************");for(i=0;i<n;i++){j=0;printf("\n");printf("\t\t%c\t",t[i].key,t[i].weight);hfmtpath(t,i,j);}printf("\n------------------------------------------------------------------\n");}void encoding(hfmt t)//对用户输入的电文进行编码{char r[1000];//用来存储输入的字符串int i,j;printf("\n\n请输入需要编码的字符:");gets(r);printf("编码结果为:");for(j=0;r[j]!='\0';j++)for(i=0;i<n;i++)if(r[j]==t[i].key)hfmtpath(t,i,j);printf("\n");}void decoding(hfmt t)//对用户输入的密文进行译码{char r[100];int i,j,len;j=2*n-2;//j初始从树的根节点开始printf("\n\n请输入需要译码的字符串:");gets(r);len=strlen(r);printf("译码的结果是:");for(i=0;i<len;i++){if(r[i]=='0'){j=t[j].lchild;if(t[j].lchild==-1){printf("%c",t[j].key);j=2*n-2;}}else if(r[i]=='1'){j=t[j].rchild;if(t[j].rchild==-1){printf("%c",t[j].key);j=2*n-2;}}}printf("\n\n");}int main(){int i,j;hfmt ht;char flag;printf(" |----------------------|\n"); printf(" |信管1002--林左权--15号|\n"); printf(" |**********************|\n"); printf(" | 哈夫曼编码课程设计 |\n"); printf(" |**********************|\n"); printf(" |设计完成时间:2011/6/27|\n"); printf(" |----------------------|\n");creathfmt(ht);printhfmt(ht);phfmnode(ht);printf("\n------------------------------------------------------------------\n");printf("***************************编码&&译码&&退出***********************");printf("\n【1】编码\t【2】\t译码\t【0】退出");printf("\n您的选择:");flag=getchar();getchar();while(flag!='0'){if(flag=='1')encoding(ht);else if(flag=='2')decoding(ht);elseprintf("您的输入有误,请重新输入。

霍夫曼编码

霍夫曼编码

#include <iostream>#include <cstring>using namespace std;#define MAX 32767typedef struct{int weight;char value;int parent;int lchild;int rchild;}HTNode, *HuffmanTree; //动态分配数组存储霍夫曼树typedef struct{char * HfmCode; //动态分配数组,存储哈夫曼编码char value;}code, *HuffmanCode;//选择最小权重的两个树void select(HuffmanTree &ht,int n,int *s1,int *s2){/*ht,为树所在数组的头指针,n为允许查找的最大序号,s1,s2,返回最小的两个序号*/int p1=MAX;int p2=MAX; /*p1, p2用来记录最小的两个权, 要求p1<p2*/int pn1=0;int pn2=0; /*pn1, pn2 用来记录这两个权的序号*/int i;for(i=1;i<=n;i++){if(ht[i].weight<p1 && ht[i].parent==0) //ht[i].parent=0的作用是去掉已经选过的节点{pn2=pn1;p2=p1;pn1=i;p1=ht[i].weight;}else if(ht[i].weight<p2 && ht[i].parent==0){pn2=i;p2=ht[i].weight;}}*s1=pn1; //赋值返回*s2=pn2;}//创建霍夫曼树void Creat_HuffmanTree(HuffmanTree &ht,int *w,char *st,int n){int m=2*n-1;ht=(HuffmanTree)malloc( (m+1)*sizeof(HTNode) ); //0号单元不用HuffmanTree p;int i;w=w+1; //因为w[]的0号单元没有用st=st+1;for(p=ht+1,i=1; i<=n; i++,p++,w++,st++ ) //1-n号放叶子结点,初始化{(*p).weight=*w;(*p).value=*st;(*p).parent=0;(*p).lchild=0;(*p).rchild=0;}for(; i<=m; i++,p++) //非叶子结点初始化{(*p).weight=0;(*p).parent=0;(*p).lchild=0;(*p).rchild=0;}int s1,s2; //在select函数中使用,用来存储最小权的结点的序号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){for(int i=1;i<=m;i++)cout<<ht[i].weight<<" ";}//从叶子结点到根,逆向求每个叶子结点对应的哈夫曼编码void Creat_HuffmanCode(HuffmanTree &ht,HuffmanCode &hc,int n){char *cd;int start;int c; //c指向当前节点int p; //p指向当前节点的双亲结点int i;hc=(HuffmanCode)malloc( (n+1)*sizeof(code) ); //分配n个编码的头指针cd=(char * )malloc(n * sizeof(char )); //分配求当前编码的工作空间 cd[n-1]='\0'; //从右向左逐位存放编码,首先存放编码结束符for(i=1;i<=n;i++) //求n个叶子结点对应的哈夫曼编码{hc[i].value=ht[i].value;start=n-1; //初始化编码起始指针for(c=i,p=ht[i].parent; p!=0; c=p,p=ht[p].parent) //从叶子到根结点求编码{if(ht[p].lchild == c)cd[--start]='0';elsecd[--start]='1';}hc[i].HfmCode = (char *)malloc(n*sizeof(char)); //为第i个编码分配空间strcpy(hc[i].HfmCode,&cd[start]);}free(cd);}//解码void Decoding_HuffmanTree(HuffmanTree &ht,char code[],char result[]) {int i , k=0 ;int p=0, root;for (root=1 ; ht[root].parent!=0 ; root=ht[root].parent); //root是霍夫曼树的根for (i=0 , p=root ; code[i]!='\0'; i++){if (code[i] == '0')p = ht[p].lchild;elsep = ht[p].rchild;if (ht[p].lchild==NULL && ht[p].rchild==NULL){result[k++] = ht[p].value;p = root;}}result[k] = '\0';}int main(){HuffmanTree HT;HuffmanCode HC;int *w; //动态数组,存放各字符的权重char *st; //字符串,存放节点的值int i,n; //n is the number of elementsint m;cout<<"input the total number of the Huffman Tree:"<<endl; cin>>n;w=(int *)malloc( (n+1)*sizeof(int) ); //0号单元不用st=(char *)malloc( (n+1)*sizeof(char) ); //0号单元不用FILE *fin=fopen("哈弗曼编码.txt","r");for(i=1;i<=n;i++){fscanf(fin,"%c%d",&st[i],&w[i]);}Creat_HuffmanTree(HT,w,st,n); /*构造H树*/m=2*n-1;outputHuffman(HT,m); /*显示H树*/cout<<endl;Creat_HuffmanCode(HT,HC,n); /*根据H树,求每个字符的编码,放在HC中*/ for(i=1;i<=n;i++) /*输出编码*/cout<<HC[i].value<<" "<<HC[i].HfmCode<<endl;//解码char *code="01101110101010001110110110011100";char *result;result=(char *)malloc(100*sizeof(char));Decoding_HuffmanTree(HT,code,result); //result[]存放解码结果for(i=0;result[i];i++)cout<<result[i]<<" ";return0;}。

霍夫曼编码

霍夫曼编码
int i,j,x1,x2,c,p;
int m1,m2;
LV_ITEM lvitem; //ListCtrl的ITEM
Int iActualItem; //中间变量,用于保存ListCtrl添加的ITEM编号
HuffmanNode * huffNode; //存放哈夫曼树的节点
int Flag; //当Flag=0时,表示该节点未加入树中,为1时表示已加入树中
int Parent; //存放节点的父节点在节点数组中的序号
int LChild; //存放节点的左子节点在节点数组中的序号
int RChild; //存放节点的右子节点在节点数组中的序号
p = huffNode[c].Parent;
}
}
}
//计算平均码字长度和图像熵
int CodeLen = 0;
m_fEntropy = 0.0;
for(i = 0;i<iNumNode;i++)
{
CodeLen += huffNode[i].Weight * strCode[i].GetLength();
x1=j;
}
else if(huffNode[j].Weight<m2 & & huffNode[j].Flag = = 0
{
m2=huffNode[j].Weight;
x2=j;
}
}
//将找出的两棵最小子树合并为一棵子树
huffNode[x1].Parent = iNumNode+1;
{
if(m_fFreq[i+m_ChannelSel * m_iLeafNum]!=0)

c++实现霍夫曼编码

c++实现霍夫曼编码

c++实现霍夫曼编码霍夫曼编码是一种非常有效的编码方式,主要用于数据压缩。

它通过选择最优的字符编码,使得编码后的数据长度最短,从而大大降低了数据的传输和存储成本。

在计算机科学中,霍夫曼编码经常被用于通信、数据压缩、网络协议等领域。

下面是一个用 C 语言实现的简单霍夫曼编码算法。

这个算法首先构建一个霍夫曼树,然后使用这个树来为输入的字符编码。

```c#include <stdio.h>#include <stdlib.h>#include <string.h>typedef struct Node {char symbol;int weight;struct Node* left;struct Node* right;} Node;Node* createNode(char symbol, int weight) {Node* newNode = (Node*)malloc(sizeof(Node));newNode->symbol = symbol;newNode->weight = weight;newNode->left = NULL;newNode->right = NULL;return newNode;}void printTree(Node* root) {if (root == NULL) {return;}printTree(root->left);printf("%c ", root->symbol);printTree(root->right);}void buildHuffmanTree(char* str, int* freq) {int n = strlen(str);int i, j;for (i = 0; i < n; i++) {freq[str[i]]++;}int tmpWeight;for (i = 1; i <= 256; i++) { //添加NULL结束符, 为了连接两颗霍夫曼树。

无失真信源编码之霍夫曼编码

无失真信源编码之霍夫曼编码

0 1
三、霍夫曼编码优缺点 优点:
霍夫曼编码效率高, 1 , 常用于文 件传真, 语音处理和图象处理的数据压 缩。
Page 14
不足之处:
(1)霍夫曼编码没有错误纠正能力,一般只 能适合于低噪声优质信道中传输。 (2)霍夫曼编码硬件实现较复杂,且需要根 据实际通信系统特性设计合适的缓冲寄存器。 (3)霍夫曼编码是概率匹配编码,需预先知 道信源的概率分布。
Page 15
谢谢各位!
信息理论与编码
无失真信源编码 ——游程编码
工程技术学院 电气与电子信息系 郭堃
课程简介
寻找通信过程中的共同规律,以提高 通信的有效性、可靠性和保密性,使通信
系统达到最优化。
Page 2
本次课内容概要
无失真信源编码 霍夫曼编码
1、编码过程及码树的构造 2、霍夫曼编码效率 3、多元霍夫曼编码
霍夫曼编码优缺点
二元huffman码的编码步骤2将码符号01分配给两个最小概率的信源符号并将其概率值合并成为一个信源符号3再重新排序分配01重复步骤2直至最后剩下两个信源01000001000114从树根到叶子节点顺序写出树枝编码即可的到相应编码page100011001000001信源符号码元page11满足式才能充分利用短码信源缩减次数若不满足则需增加每次合并时信源符号减少的数量page12huffman033032031030020100page13霍夫曼编码效率高常用于文件传真语音处理和图象处理的数据压优点
S1
01 000 0010 0011
s1 0.4
0
1
s2 0.2
0 1
s3 0.2
0
1
s4
s5
P( s i )

霍夫曼编码代码

霍夫曼编码代码

霍夫曼编码代码霍夫曼编码是一种用于数据压缩的无损编码算法,它通过将出现频率较高的字符用较短的编码表示,而将出现频率较低的字符用较长的编码表示,从而实现对数据的压缩。

下面是一个用Python实现霍夫曼编码的参考代码:```pythonfrom heapq import heappop, heappushfrom collections import defaultdictdef build_frequency_table(data):frequency_table = defaultdict(int)for char in data:frequency_table[char] += 1return frequency_tabledef build_huffman_tree(frequency_table):heap = [[weight, [char, ""]] for char, weight infrequency_table.items()]while len(heap) > 1:lo = heappop(heap)hi = heappop(heap)for pair in lo[1:]:pair[1] = '0' + pair[1]for pair in hi[1:]:pair[1] = '1' + pair[1]heappush(heap, [lo[0] + hi[0]] + lo[1:] + hi[1:])return heap[0]def build_encoding_table(huffman_tree):encoding_table = {}for char, code in huffman_tree[1:]:encoding_table[char] = codereturn encoding_tabledef huffman_encode(data):frequency_table = build_frequency_table(data)huffman_tree = build_huffman_tree(frequency_table)encoding_table = build_encoding_table(huffman_tree)encoded_data = ''.join(encoding_table[char] for char in data)return encoded_datadef huffman_decode(encoded_data, huffman_tree):decoding_table = {code: char for char, code in huffman_tree[1:]} current_code = ''decoded_data = ''for bit in encoded_data:current_code += bitif current_code in decoding_table:char = decoding_table[current_code]decoded_data += charcurrent_code = ''return decoded_data# 示例用法data = 'hello world'encoded_data = huffman_encode(data)print(encoded_data)decoded_data = huffman_decode(encoded_data,build_huffman_tree(build_frequency_table(data)))print(decoded_data)```以上代码中,`build_frequency_table()`函数用于构建字符出现频率的字典,`build_huffman_tree()`函数构建霍夫曼树,`build_encoding_table()`函数构建字符编码表,`huffman_encode()`函数对数据进行编码,`huffman_decode()`函数对编码后的数据进行解码。

java源程序 哈夫曼编码

java源程序 哈夫曼编码

java源程序哈夫曼编码实现Huffman编码需要编写一些代码,因此我将提供一个简单的Java程序,演示如何使用Huffman编码对文本进行压缩和解压缩。

这个例子仅用于演示基本概念,实际使用中可能需要进行更多的优化和错误处理。

```javaimport java.util.PriorityQueue;import java.util.HashMap;import java.util.Map;class HuffmanNode implements Comparable<HuffmanNode> {char data;int frequency;HuffmanNode left, right;public HuffmanNode(char data, int frequency) {this.data = data;this.frequency = frequency;}@Overridepublic int compareTo(HuffmanNode o) {return this.frequency - o.frequency;}}public class HuffmanCoding {private static Map<Character, String> huffmanCodes = new HashMap<>();public static void main(String[] args) {String inputText = "hello world";Map<Character, Integer> frequencyMap = buildFrequencyMap(inputText);HuffmanNode root = buildHuffmanTree(frequencyMap);generateHuffmanCodes(root, "", huffmanCodes);System.out.println("Original Text: " + inputText);String encodedText = encode(inputText);System.out.println("Encoded Text: " + encodedText);String decodedText = decode(encodedText, root);System.out.println("Decoded Text: " + decodedText);}private static Map<Character, Integer> buildFrequencyMap(String text) {Map<Character, Integer> frequencyMap = new HashMap<>();for (char c : text.toCharArray()) {frequencyMap.put(c, frequencyMap.getOrDefault(c, 0) + 1);}return frequencyMap;}private static HuffmanNode buildHuffmanTree(Map<Character, Integer> frequencyMap) { PriorityQueue<HuffmanNode> priorityQueue = new PriorityQueue<>();for (Map.Entry<Character, Integer> entry : frequencyMap.entrySet()) {priorityQueue.add(new HuffmanNode(entry.getKey(), entry.getValue()));}while (priorityQueue.size() > 1) {HuffmanNode left = priorityQueue.poll();HuffmanNode right = priorityQueue.poll();HuffmanNode mergedNode = new HuffmanNode('\0', left.frequency + right.frequency);mergedNode.left = left;mergedNode.right = right;priorityQueue.add(mergedNode);}return priorityQueue.poll();}private static void generateHuffmanCodes(HuffmanNode root, String code, Map<Character, String> huffmanCodes) {if (root != null) {if (root.left == null && root.right == null) {huffmanCodes.put(root.data, code);}generateHuffmanCodes(root.left, code + "0", huffmanCodes);generateHuffmanCodes(root.right, code + "1", huffmanCodes);}}private static String encode(String text) {StringBuilder encodedText = new StringBuilder();for (char c : text.toCharArray()) {encodedText.append(huffmanCodes.get(c));}return encodedText.toString();}private static String decode(String encodedText, HuffmanNode root) {StringBuilder decodedText = new StringBuilder();HuffmanNode current = root;for (char bit : encodedText.toCharArray()) {if (bit == '0') {current = current.left;} else if (bit == '1') {current = current.right;}if (current.left == null && current.right == null) {decodedText.append(current.data);current = root;}}return decodedText.toString();}}```请注意,这只是一个简单的示例,实际上Huffman编码可能涉及到更多的细节和考虑因素。

霍夫曼编码(含源程序)

霍夫曼编码(含源程序)

多媒体技术基础实验报告——霍夫曼编码学院:电子工程与光电技术学院专业:电子信息工程姓名:学号:任课老师:康其桔实验时间:一、实验内容及要求1、使用Matlab 编程实现霍夫曼编码2、通过键盘输入字符串3、在屏幕上显示编码结果二、实验原理霍夫曼编码是霍夫曼在1952年提出和描述的“从下到上”的熵编码方法。

根据给定数据集中各元素所出现的频率来压缩数据的一种统计压缩编码方法。

这些元素(如字母)出现的次数越多,其编码的位数就越少。

其基本步骤为: (1) 将压缩的各字符的出现概率按减少(或增加)的顺序进行排列。

(2) 将两个最小的概率进行组合相加得到一个新概率将这一新概率与其它概率一起继续执行1 和2 的操作直至最后概率为1.0。

(3) 对每对组合中的概率较大者指定为1,较小者指定为0。

(4) 画出由每个信源符号概率到1.0处的路径记下路径的1和0。

(5) 对每个信源符号由从右到左写出1/0序列,对概率较高的标1,对概率较低的标0(或对概率较高的标0,对概率较低的标1),就得到了对应的Huffman 码。

下面举个例子来说明霍夫曼编码的具体过程。

设需要编码的信息为:BACDEBACDEBACDEBADEBAEBABABABB,统计各个字符出现的次数分别为B(10次)、A(8次)、C(3次)、D(4次)、E(5次)。

各个字符出现的概率为B(10/30)、A(8/30)、E(5/30)、D(4/30)、C(3/30)。

霍夫曼编码的过程如下: B(10/30)A(8/30)E(5/30) D(4/30) C(3/30) 霍夫曼编码后平均码长为2(10/308/305/30)3(4/303/30) 2.23b ⨯+++⨯+≈ 。

而信源熵 2.19H b =。

由此,我们可以看出,霍夫曼编码结果已经很接近理想信源熵。

三、设计方案设计的流程图如下:7/30 12/3018/30 30/30 B:11 A:10 E:00 D:011 C:010 1 010 0 1 1 0四、各模块设计(一)读入字符串并去除空格在Matalb中使用语句inputstring=input('请输入需要编码的字符:','s'),输入的字符串存入char型数组inputstring中。

霍夫曼编码代码

霍夫曼编码代码

霍夫曼编码代码简介霍夫曼编码是一种常用的无损数据压缩算法,广泛应用于数据传输和存储中。

它通过构建一棵霍夫曼树,将出现频率较高的字符用较少的二进制位表示,从而达到压缩数据的目的。

本文将详细介绍霍夫曼编码的原理、实现方式以及编写霍夫曼编码的代码示例。

霍夫曼编码原理霍夫曼编码的核心原理是根据字符出现的频率构建一棵霍夫曼树。

树的叶子节点对应字符,叶子节点到根节点的路径上的分支标记为0或1,构成了字符的霍夫曼编码。

编码的规则是,出现频率较高的字符对应的编码较短,而出现频率较低的字符对应的编码较长。

霍夫曼编码的步骤1.统计字符的频率:遍历待压缩的数据,统计每个字符出现的次数。

2.构建霍夫曼树:将字符频率作为权值创建一棵霍夫曼树,其中频率较低的字符位于树的下层。

3.生成霍夫曼编码表:从霍夫曼树的根节点开始,向左走的路径标记为0,向右走的路径标记为1,递归生成每个字符对应的霍夫曼编码。

4.压缩数据:按照生成的编码将原始数据转换成二进制字符串,将字符串转换为字节流保存。

实现霍夫曼编码的关键数据结构在实现霍夫曼编码时,我们需要以下两个关键的数据结构: 1. 霍夫曼树:用于构建霍夫曼编码,其节点包含字符和对应的频率。

2. 霍夫曼编码表:用于存储每个字符对应的编码。

伪代码实现下面是一个简单的伪代码实现霍夫曼编码的例子:# 伪代码实现霍夫曼编码def huffman_encoding(data):# 统计字符频率freq_map = count_frequency(data)# 构建霍夫曼树huffman_tree = build_huffman_tree(freq_map)# 生成霍夫曼编码表huffman_code_table = generate_code_table(huffman_tree)# 压缩数据encoded_data = encode_data(data, huffman_code_table)return encoded_data, huffman_code_table实例演示为了更好理解霍夫曼编码的过程,我们以字符串”hello world”为例进行演示。

霍夫曼编码

霍夫曼编码

霍夫曼编码(Huffman Coding)是一种编码方式,是一种用于无损数据压缩的熵编码(权编码)算法。

1952年,David A. Huffman在麻省理工攻读博士时所发明的,并发表于《一种构建极小多余编码的方法》(A Method for the Construction of Minimum-Redundancy Codes)一文。

在电脑资料处理中,霍夫曼编码使用变长编码表对源符号(如文件中的一个字母)进行编码,其中变长编码表是通过一种评估来源符号出现机率的方法得到的,出现机率高的字母使用较短的编码,反之出现机率低的则使用较长的编码,这便使编码之后的字符串的平均长度、期望值降低,从而达到无损压缩数据的目的。

例如,在英文中,e的出现机率最高,而z的出现概率则最低。

当利用霍夫曼编码对一篇英文进行压缩时,e极有可能用一个位元来表示,而z则可能花去25个位元(不是26)。

用普通的表示方法时,每个英文字母均占用一个字节(byte),即8个位元。

二者相比,e使用了一般编码的1/8的长度,z则使用了3倍多。

倘若我们能实现对于英文中各个字母出现概率的较准确的估算,就可以大幅度提高无损压缩的比例。

霍夫曼树又称最优二叉树,是一种带权路径长度最短的二叉树。

所谓树的带权路径长度,就是树中所有的叶结点的权值乘上其到根结点的路径长度(若根结点为0层,叶结点到根结点的路径长度为叶结点的层数)。

树的路径长度是从树根到每一结点的路径长度之和,记为WPL= (W1*L1+W2*L2+W3*L3+...+Wn*Ln),N个权值Wi(i=1,2,...n)构成一棵有N个叶结点的二叉树,相应的叶结点的路径长度为Li(i=1,2,...n)。

可以证明霍夫曼树的WPL是最小的。

霍夫曼(Huffman)编码原理计算法霍夫曼(Huffman)编码是1952年为文本文件而建立,是一种统计编码。

属于无损压缩编码。

霍夫曼编码的码长是变化的,对于出现频率高的信息,编码的长度较短;而对于出现频率低的信息,编码长度较长。

霍夫曼编码c语言

霍夫曼编码c语言

霍夫曼编码c语言霍夫曼编码是一种用于数据压缩的编码技术,它通过重新组织数据中的符号来减少传输或存储数据所需的比特数。

在C语言中实现霍夫曼编码需要掌握数据结构、算法和编码理论的基础知识。

一、霍夫曼编码原理霍夫曼编码的基本原理是利用符号出现的频率来构建一个最优的编码方案,使得编码后的比特率最小。

在霍夫曼图中,每个符号对应一个唯一的路径,路径上的节点表示该符号可能出现的概率。

通过选择概率较大的路径,可以获得较短的编码,从而实现数据压缩。

二、C语言实现霍夫曼编码以下是一个简单的C语言实现霍夫曼编码的示例代码:```c#include<stdio.h>#include<stdlib.h>#include<stdbool.h>//定义霍夫曼树节点结构体typedefstructNode{charsymbol;//符号structNode*left;//左子节点structNode*right;//右子节点intfrequency;//符号频率}Node;//构建霍夫曼树函数Node*buildHuffmanTree(intfrequencies[],intn){//合并相同频率的节点for(inti=0;i<n-1;i++){for(intj=i+1;j<n;j++){if(frequencies[i]==frequencies[j]){ Node*temp=frequencies[i]; frequencies[i]=frequencies[j]; frequencies[j]=temp;mergeNodes(frequencies,i,j);}}}//构建霍夫曼树Node*root=NULL;for(inti=0;i<n;i++){if(root==NULL){root=frequencies[i];}else{Node*child=frequencies[i];child->left=root;root->right=child;root=child;}}returnroot;}//合并两个节点的函数voidmergeNodes(intfrequencies[],inti,intj){frequencies[i]=frequencies[j];//合并节点频率frequencies[j]=NULL;//移除多余节点}//输出霍夫曼编码函数voidprintCodes(Node*root,char*codes[],intindex){if(root==NULL){//如果节点为空,输出编码为空字符串printf("%s",codes[index]);return;}elseif(root->left!=NULL){//如果节点左子节点不为空,输出左子节点的编码作为前缀printCodes(root->left,codes,index*2+1);}elseif(root->right!=NULL){//如果节点右子节点不为空,输出右子节点的编码作为前缀(可用作解码的辅助信息)printCodes(root->right,codes,index*2+2);}else{//如果节点为叶子节点,输出节点的符号作为编码的前缀(去掉重复前缀)并输出当前编码的长度(作为该符号的出现次数)intfreq=root->frequency;//当前符号频率(去掉重复前缀后的频率)while(codes[index]!='\0'){//将前缀放入已使用的字符串数组中以供其他叶子节点使用,重复前缀使用最少的次数(去除重复)并输出当前编码长度和符号本身作为输出结果index--;//指针向后移动一位,直到指针指向'\0'字符为止(已使用的字符串数组)或遇到NULL字符为止(编码数组结束)并返回编码长度和符号本身作为输出结果供其他叶子节点使用和参考。

霍夫曼编码(含源程序)

霍夫曼编码(含源程序)

多媒体技术基础实验报告——霍夫曼编码学院:电子工程与光电技术学院专业:电子信息工程姓名:学号:任课老师:康其桔实验时间:一、实验内容及要求1、使用Matlab 编程实现霍夫曼编码2、通过键盘输入字符串3、在屏幕上显示编码结果二、实验原理霍夫曼编码是霍夫曼在1952年提出和描述的“从下到上”的熵编码方法。

根据给定数据集中各元素所出现的频率来压缩数据的一种统计压缩编码方法。

这些元素(如字母)出现的次数越多,其编码的位数就越少。

其基本步骤为: (1) 将压缩的各字符的出现概率按减少(或增加)的顺序进行排列。

(2) 将两个最小的概率进行组合相加得到一个新概率将这一新概率与其它概率一起继续执行1 和2 的操作直至最后概率为1.0。

(3) 对每对组合中的概率较大者指定为1,较小者指定为0。

(4) 画出由每个信源符号概率到1.0处的路径记下路径的1和0。

(5) 对每个信源符号由从右到左写出1/0序列,对概率较高的标1,对概率较低的标0(或对概率较高的标0,对概率较低的标1),就得到了对应的Huffman 码。

下面举个例子来说明霍夫曼编码的具体过程。

设需要编码的信息为:BACDEBACDEBACDEBADEBAEBABABABB,统计各个字符出现的次数分别为B(10次)、A(8次)、C(3次)、D(4次)、E(5次)。

各个字符出现的概率为B(10/30)、A(8/30)、E(5/30)、D(4/30)、C(3/30)。

霍夫曼编码的过程如下: B(10/30)A(8/30)E(5/30) D(4/30) C(3/30) 霍夫曼编码后平均码长为2(10/308/305/30)3(4/303/30) 2.23b ⨯+++⨯+≈ 。

而信源熵 2.19H b =。

由此,我们可以看出,霍夫曼编码结果已经很接近理想信源熵。

三、设计方案设计的流程图如下:7/30 12/3018/30 30/30 B:11 A:10 E:00 D:011 C:010 1 010 0 1 1 0四、各模块设计(一)读入字符串并去除空格在Matalb中使用语句inputstring=input('请输入需要编码的字符:','s'),输入的字符串存入char型数组inputstring中。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
//---------------------------------------------/*第步:queue建立二叉树数据结构 * */ //---------------------------------------------void huffuman_codelist(struct node *queue) { int i=0; //21,---------------------------------建立并且初始化二叉树的root,即把排序好的队列 的第一个赋值给root; struct node *root=(struct node *)malloc(sizeof(struct node)); for( i=0;i<256;i++){
Hufuman.c 源文件
#include "hufuman.h" extern char codelist[256][10]; extern unsigned char uncode[256][2]; //节点插入法 struct node * insert(struct node * root,struct node *s){
root=last_n;//-------------将链表的首地址取出; //----------------------测试 printf("\n---------------------------------------------------------\n"); struct node *p1=root;
} return root;//返回链表头指针地址 }
//----------------------------------------------
/*第步:打开文件,并且统计文件中各种字符出现的次数number,按照出现的次
数从小到大的存入数组queue[]中+测试函数
*
*/
//----------------------------------------------
//----------------------初始化数组
for(int i=0;i<256;i++){
queue[i].name=i;
//初始化字符
queue[i].number=0; //初始化字符出现的次数
}
//
//------------Fra bibliotek---------统计权值大小
char ch;
while((ch=fgetc(trj_src))!=EOF){
霍夫曼编码算法 语言:C 开发工具:VS2008 实现流程: 第 1 步: 打开文件, 并且统计文件中各种字符出现的次数 number, 按照出现的 次数从小到大的存入数组 queue[] 第 2 步:顺序的按次数小到大排列到数组中 第 3 步:依据 queue[]建立二叉树数据结构 31,-建立并且初始化二叉树的 root,即把排序好的队列的 第 一 个 赋值给 root。 32,将数组建立成有序链表,初始化左右子树 33,建立二叉树 第 4 步:根据二叉树结构建立编码表,解码表 第 5 步:编码 我们要把文件的字符按照编码表编码为一个二进制流,然后每取 8 个 位装入在一个字符中,并存入文件。 第 5 步:解码 从压缩文件里不断的取出字符作为一个二进制流看待,从左到右挨个 测试为 0 还是为 1,转换为 10 进制值,测试十进制值的大小对应在 解码表里有编码的字符,而且字符表里记录的该字符对应的编码位数 等于你从二进制流里取出来转换为进制值的个数时,转换为对应的解 码表里的字符。
if(queue[i].number==0)continue; struct node *link_n=(struct node *)malloc(sizeof(struct node));
link_n->left_child =NULL; link_n->right_child =NULL; link_n->name=queue[i].name; link_n->number=queue[i].number; link_n->bit[0]='\0'; link_n->next=last_n; last_n=link_n; }
unsigned char uncode[256][2]={0}; //----------------------------//--------------------------------------------------------------
int main(){
trj_queue(queue,&src_length); printf("\n---------------------------------------------------------\n"); trj_sort(queue); printf("\n---------------------------------------------------------\n"); huffuman_codelist(queue); printf("\n---------------------------------------------------------\n"); huffman_code(); printf("\n---------------------------------------------------------\n"); huffman_uncode();
struct node * p1,*p2; if(root==NULL)root=s; else{
p1=NULL; p2=root; while(p2 && p2->number < s->number){/*查找插入位置*/
p1=p2; p2=p2->next; } //---------------------------找到了位置,在P1与P2之间 //---------------------------把新节点S的下一个节点指针指向P2,P2的上一个节点的 next指向新节点S //---------------------------P1-S-P2 s->next=p2; if(p1==NULL) root=s; else p1->next=s;
char name;//记录字符
int number;//字符出现的次数 char bit[10];//编码值 struct node *left_child,*right_child,*next; };
struct node * insert(struct node * root,struct node *s);
struct node *right,*left;
//root指向的是链表的首地址,将前两个节点拿出来 left=root; right=root->next;
//将root转移到链表的第三个位置 root=right->next;
void trj_queue(struct node *queue, long *src_length)
{
FILE *trj_src;
//----------------------判断文件是否打开成功
if((trj_src=fopen("1.txt","r"))==NULL){printf("open file no %s\n");exit(1); }
if(queue[i].number!=0){ root->left_child =NULL; root->right_child =NULL; root->name=queue[i].name; root->number=queue[i].number; root->next=NULL; root->bit[0]='\0'; i++; break; } } //22,----------------------------------将数组建立成有序链表,初始化左右子树 struct node *last_n=root;//--------------将链表的尾地址取出 for(;i<256;i++){
while(p1!=NULL){ printf("%d (%c) ",p1->number,p1->name); p1=p1->next;
} //23,-----------------------------------------------------------建立二叉树
while(root && root->next) {
说明:压缩文件中网页是参考资料
附源代码: Man.c 主函数
#include "hufuman.h" //---------------------------------------------typedef struct node huff_node; typedef struct node *huff_link; huff_node queue[256];//霍夫曼树结构体数组 long src_length;//------------------------记录源文件的字符个数 //--------------------编码对照表 char codelist[256][10]={0};
queue[ch].number++; //----权值加
putchar(ch);
//-------------测试输出字符
src_length[0]++; //----------用于记录文件的长度
相关文档
最新文档