1、哈夫曼编码HuffmanCoding哈夫曼编码哈夫曼编码(Huffman Coding)是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种。 Huffman于1952年提出一种编码方式,该方式完全依据字符显现概率来构造异字头的平均长 度最短的码字,有时称之为最正确编码,一样就叫作Huffman编码。 以即最优二叉树,带权途径长度最小的二叉树,常常应用于数据紧缩。 在运算机信息处置中,“哈夫曼编码”是一种一致性编码法(又称熵编码法),用于数据的无损耗紧缩。这一术语是指利用一张特殊的编码表将源字符(例如某文件中的一个符号)进行编码。这张编码表的特殊的地方在于,它是依照每一个源字符显现的估算概
2、率而成立起来的(显现概率高的字符利用较短的编码,反之显现概率低的那么利用较长的编码,这便使编码以后的字符串的平均期望长度降低,从而达到无损紧缩数据的目的)。这种方式是由进展起来的。 例如,在英文中,e的显现概率很高,而z的显现概率那么最低。当利用哈夫曼编码对一篇英文进行紧缩时,e极有可能用一个位(bit)来表示,而z那么可能花去25个位(不是26)。用一般的表示方式时,每一个英文字母均占用一个字节(byte),即8个位。二者相较,e利用了一样编码的1/8的长度,z那么利用了3倍多。倘假设咱们能实现关于英文中各个字母显现概率的较准确的估算,就能够够大幅度提高无损紧缩的比例。 本文描述在网上能够找
3、到的最简单,最快速的哈夫曼编码。本方式不利用任何扩展动态库,比如STL或组件。只利用简单的C函数,比如:memset,memmove,qsort,malloc,realloc和memcpy。 因此,大伙儿都会发觉,明白得乃至修改那个编码都是很容易的。背景哈夫曼紧缩是个无损的紧缩算法,一样用来紧缩文本和程序文件。哈夫曼紧缩属于可变代码长度算法一族。意思是个体符号(例如,文本文件中的字符)用一个特定长度的位序列替代。因此,在文件中显现频率高的符号,利用短的位序列,而那些很少显现的符号,那么用较长的位序列。编码利用我用简单的C函数写那个编码是为了让它在任何地址利用都会比较方便。你能够将他们放到类中,
4、或直接利用那个函数。而且我利用了简单的格式,仅仅输入输出缓冲区,而不象其它文章中那样,输入输出文件。bool CompressHuffman(BYTE *pSrc, int nSrcLen, BYTE *&pDes, int &nDesLen);bool DecompressHuffman(BYTE *pSrc, int nSrcLen, BYTE *&pDes, int &nDesLen);要点说明 速度为了让它快速运行,我花了很长时刻。同时,我没有利用任何动态库,比如STL或MFC。它紧缩1M数据少于100ms(P3处置器,主频1G)。紧缩紧缩代码超级简单,第一用ASCII值初始化511个
5、哈夫曼节点: CHuffmanNode nodes511;for(int nCount = 0; nCount 256; nCount+)nodesnCount.byAscii = nCount;然后,计算在输入缓冲区数据中,每一个ASCII码显现的频率: for(nCount = 0; nCount nSrcLen; nCount+)nodespSrcnCount.nFrequency+;然后,依照频率进行排序: qsort(nodes, 256, sizeof(CHuffmanNode), frequencyCompare);此刻,构造哈夫曼树,获取每一个ASCII码对应的位序列: int
6、 nNodeCount = GetHuffmanTree(nodes);构造哈夫曼树超级简单,将所有的节点放到一个队列中,用一个节点替换两个频率最低的节点,新节点的频率确实是这两个节点的频率之和。如此,新节点确实是两个被替换节点的父节点了。如此循环,直到队列中只剩一个节点(树根)。 wCode 3): 3 以8位为界限右移后抵达右边字节的前面 (nDesIndex&7): &7 取得最高位. 注意:在紧缩缓冲区中,咱们必需保留哈夫曼树的节点和位序列,如此咱们才能在解紧缩时从头构造哈夫曼树(只需保留ASCII值和对应的位序列)。 解紧缩解紧缩比构造哈夫曼树要简单的多,将输入缓冲区中的每一个编码用
7、对应的ASCII码逐个替换就能够够了。只要记住,那个地址的输入缓冲区是一个包括每一个ASCII值的编码的位流。因此,为了用ASCII值替换编码,咱们必需用位流搜索哈夫曼树,直到发觉一个叶节点,然后将它的ASCII值添加到输出缓冲区中: int nDesIndex = 0;DWORD nCode;while(nDesIndex 3)(nSrcIndex&7);pNode = pRoot;while(pNode-pLeft)pNode = (nCode&1) ? pNode-pRight : pNode-pLeft;nCode = 1;nSrcIndex+;pDesnDesIndex+ = pNo
8、de-byAscii;进程#include #include#include#include#include#define M 10typedef struct Fano_Node char ch;float weight;FanoNodeM;typedef struct nodeint start;int end;struct node *next;LinkQueueNode;typedef struct LinkQueueNode *front;LinkQueueNode *rear;LinkQueue;void EnterQueue(LinkQueue *q,int s,int e)Li
9、nkQueueNode *NewNode;NewNode=(LinkQueueNode *)malloc(sizeof(LinkQueueNode);if(NewNode!=NULL)NewNode-start=s;NewNode-end=e;NewNode-next=NULL;q-rear-next=NewNode;q-rear=NewNode;else printf(Error!);h)printf(Same noden);break;if(i=j) i+; for(i=1;i=n;i+) /*排序*/ max=i+1;for(j=max;j=n;j+)max=FNmax.weightFN
10、j.weight?j:max;ifFNmax.weight)w=;=FNmax.weight;FNmax.weight=w;c=;=FNmax.ch;FNmax.ch=c; for(i=1;ifront-next!=NULL) p=Q-front-next; /*出队*/ Q-front-next=p-next;if(p=Q-rear) Q-rear=Q-front;sta=p-start;end=p-end; free(p);Divide(FN,sta,&m,end); /*按权分组*/ for(i=sta;i=m;i+)fch=0;h+;if(sta!=m) EnterQueue(Q,st
11、a,m); else fcstahsta=0;for(i=m+1;i=end;i+)fch=1;h+; if(m=sta&(m+1)=end) =ch;(*CW)*p.weight=1;for(k=i+1;chk!=0;k+)if(ch=chk)(*CW)*p.weight+;*s=i; /*创建HuffmanTree*/ void CreateHuffmanTree(Huffman *ht,WeightNode w,int n) int i,j;int s1,s2;for(i=1;i=n;i+)(*ht).weight =;(*ht).parent=0;(*ht).LChild=0;(*ht
12、).RChild=0;for(i=n+1;i=2*n-1;i+)(*ht).weight=0;(*ht).parent=0;(*ht).LChild=0;(*ht).parent=0;for(i=n+1;i=2*n-1;i+)for(j=1;j=i-1;j+)if(!(*ht)j.parent)break;s1=j; /*找到第一个双亲不为零的结点*/ for(;j(*ht)j.weight?j:s1;(*ht)s1.parent=i;(*ht).LChild=s1;for(j=1;j=i-1;j+)if(!(*ht)j.parent)break;s2=j; /*找到第一个双亲不为零的结点*/
13、 for(;j(*ht)j.weight?j:s2;(*ht)s2.parent=i;(*ht).RChild=s2; (*ht).weight=(*ht)s1.weight+(*ht)s2.weight; /*叶子结点的编码*/ void CrtHuffmanNodeCode(Huffman ht,char ch,HuffmanCode *h,WeightNode *weight,int m,int n) int i,j,k,c,p,start;char *cd;cd=(char *)malloc(n*sizeof(char);cdn-1=0;for(i=1;i=n;i+) start=n-
14、1; c=i; p=; while(p) start-; if(htp.LChild=c) cdstart=0; else cdstart=1; c=p; p=htp.parent; (*weight).num=n-start; (*h)=(char *)malloc(n-start)*sizeof(char); p=-1;strcpy(*h),&cdstart); system(pause);/*所有字符的编码*/void CrtHuffmanCode(char ch,HuffmanCode h,HuffmanCode *hc,WeightNode weight,int n,int m)in
15、t i,j,k;for(i=0;im;i+)for(k=1;k=n;k+) /*从(*weight)k.c中查找与ch相等的下标K*/if(ch=weightk.c) break;(*hc)=(char *)malloc(weightk.num+1)*sizeof(char);for(j=0;j=weightk.num;j+)(*hc)j=hkj; /*解码*/ void TrsHuffmanTree(Huffman ht,WeightNode w,HuffmanCode hc,int n,int m)int i=0,j,p;printf(*StringInformation*n);while
16、(im)p=2*n-1;for(j=0;hcj!=0;j+)if(hcj=0)p=htp.LChild;elsep=htp.RChild;printf(%c,wp.c); /*打印原信息*/i+; main() int i,n,m,s1,s2,j; /*n为叶子结点的个数*/ char chN,wN; /*chN寄存输入的字符串*/ Huffman ht; /*二叉数 */HuffmanCode h,hc; /* h寄存叶子结点的编码,hc 寄存所有结点的编码*/WeightNode weight; /*寄存叶子结点的信息*/ printf(t*HuffmanCoding*n); printf
17、(please input information :);gets(ch); /*输入字符串*/ CreateWeight(ch,&m,&weight,&n); /*产生叶子结点信息,m为字符串ch的长度*/ printf(*WeightInformation*n Node ); /*输出叶子结点的字符与权值*/ for(i=1;i=n;i+)printf(%c ,;printf(nWeight );for(i=1;i=n;i+)printf(%d ,; CreateHuffmanTree(&ht,weight,n); /*产生Huffman树*/ printf(n*HuffamnTreeIn
18、formation*n); for(i=1;i=2*n-1;i+) /*打印Huffman树的信息*/ printf(t%d %d %d %dn,i,; CrtHuffmanNodeCode(ht,ch,&h,&weight,m,n); /*叶子结点的编码*/printf( *NodeCode*n); /*打印叶子结点的编码*/ for(i=1;i=n;i+) printf(t%c:,; printf(%sn,h);CrtHuffmanCode(ch,h,&hc,weight,n,m); /*所有字符的编码*/ printf(*StringCode*n); /*打印字符串的编码*/ for(i
19、=0;im;i+)printf(%s,hc);system(pause);TrsHuffmanTree(ht,weight,hc,n,m); /*解码*/ system(pause); Matlab 中简易实现Huffman编译码:n=input(Please input the total number: );hf=zeros(2*n-1,5);hq=;for ki=1:nhf(ki,1)=ki;hf(ki,2)=input(Please input the frequency: );hq=hq,hf(ki,2);endfor ki=n+1:2*n-1hf(ki,1)=ki;mhq1=min
20、(hq);m=size(hq);m=m(:,2);k=1;while k=m%del min1if hq(:,k)=mhq1hq=hq(:,1:(k-1) hq(:,(k+1):m);m=m-1;breakelsek=k+1;endendk=1;while hf(k,2)=mhq1|hf(k,5)=1%find min1 locationk=k+1;endhf(k,5)=1;k1=k;mhq2=min(hq);k=1;while k=ndisplay(Error! You did not input this number.);breakendendif k=nbreakendr=;while
21、 hf(k,5)=1kc=n+1;while hf(kc,3)=k&hf(kc,4)=kkc=kc+1;endif hf(kc,3)=kr=0 r;elser=1 r;endk=kc;endrelsea=input(Please input the metrix you want to Decoding: );sa=size(a);sa=sa(:,2);k=2*n-1;while sa=0if a(:,1)=0k=hf(k,3);elsek=hf(k,4);enda=a(:,2:sa);sa=sa-1;if k=0display(Error! The metrix you entered is a wrong one.);breakendendif k=0breakendr=hf(k,2);rendchoose=input(Please choose what you want:n1: Encodingn2: Decodingn3:.Exitn);clcendif choose=1&choose=2clc;end
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1