For details, please refer to the previous blog: Optimal Huffman coding based on binary tree and doubly linked list for limiting length
There is a significant difference in efficiency between array-based and linked-list-based implementations:
Encode 256 symbols with a symbol weight of 1 ... 256, limit the length to 16, loop encode 1w times, release mode. Based on the time of the linked list is 8972ms, the array-based time is 1793MS, the speed is 5 times times the way of the list implementation.
Detailed code such as the following:
REFERENCE:A fast algorithm for optimal length-limited Huffman Codes.pdf,http://pan.baidu.com/s/1o6e19bs//author:by Pan Yumin.2014-06-18//with the method of BinaryTree and Linked-list#include <stdio.h> #include <memory.h># Include <malloc.h> #define Maxsymbols 256//the Maximum number of symbols#define maxhufflen16//the Limited Lengthtyp Edef unsigned char boolean; #ifndef false//in case these macros already exist#define false0//values of Boolean#endif#ifndef True#define true1#endiftypedef struct __node{int width;int weight;int index;int depth;struct __Node *left;//left childst Ruct __node *right;//right child}node;typedef struct __hufftable{unsigned int index;unsigned int len;unsigned int code;} Hufftable;//test memory Leak/*int g_malloc = 0,g_free = 0;void* my_malloc (int size) {G_malloc++;return malloc (size);} void My_free (void *ptr) {if (PTR) {g_free++;free (PTR);p tr = NULL;}} #define MALLOC my_malloc#define free My_free*///get The smallest term in the diadic expansion of Xint Getsmallestterm (int X) {int N=0;while ((x & 0x01) = = 0) {X >>= 1; n++;} return 1<<n;} void Removenodemark (Node *tree,unsigned char *flag,int Symbols) {if (Tree->left = = NULL && Tree->right = = NUL L) {Flag[tree->depth*symbols+tree->index] = 0;//set the Nodemark zero}if (tree->left) {RemoveNodeMark (tree- >left,flag,symbols);} if (tree->right) {Removenodemark (tree->right,flag,symbols);}} void Printhuffcode (hufftable huffcode) {int i;for (i=huffcode.len-1;i>=0;i--) {printf ("%d", (huffcode.code>> i) & 0x01);}} void Generatehuffmancode (hufftable *huffcode,unsigned char *flag,int l,int symbols,int *sortindex) {char Code[17];int pre_l = 0;int i=0,j=0;unsigned int codes[maxhufflen+2]={0},rank[maxhufflen+1] = {0};//rank:the number of symbols in every Length//find the first codefor (i=0;i<symbols;i++) {for (j=0;j<l;j++) {Huffcode[i].len + = Flag[j*symbols+i];} if (Huffcode[i].len! = 0) rank[huffcode[i].len]++; Huffcode[i].index = Sortindex[i];} for (i=0;i<=l;i+ +) {codes[i+1] = (Codes[i]+rank[i]) <<1;rank[i] = 0;} Codefor (i=0;i<symbols;i++) {Huffcode[i].code = Codes[huffcode[i].len] + rank[huffcode[i].len]++;}} Float Bitspersymbol (hufftable *huffcode,int *weight,int symbols,int WeightSum) {float Bitspersymbol = 0.0;int i;for (i=0; i<symbols;i++) {Bitspersymbol + = (float) huffcode[i].len*weight[i];} return bitspersymbol/weightsum;} Ascending ordervoid freqsort (int *freq,int *sortindex,int Symbols) {int i,j,tmp;for (i=0;i<symbols;i++) {for (j=i+1 ; j<symbols;j++) {if (Freq[i]>freq[j]) {tmp = Freq[i]; Freq[i] = Freq[j]; FREQ[J] = Tmp;tmp = Sortindex[i]; Sortindex[i] = Sortindex[j]; SORTINDEX[J] = tmp;}}}} Ascending order, quick sortvoid QuickSort (int *arr, int *sortindex,int startpos,int endpos) {int i,j,key,index; key=arr[ Startpos];index = Sortindex[startpos];i = Startpos;j = Endpos; while (I < J) {while (Arr[j]>=key && i<j)--j;arr[i]=arr[j]; Sortindex[i] = sortindex[j];while (arr[i]<=key && i<j) ++i; Arr[j]=arr[i]; SorTINDEX[J] = Sortindex[i];} Arr[i]=key; Sortindex[i] = index;if (i-1 > Startpos) QuickSort (arr,sortindex,startpos,i-1); if (Endpos > I+1) QuickSort (arr, Sortindex,i+1,endpos); }int genlenlimitedopthuffcode (int *freq,int Symbols) {int i,j;unsigned char *flag = Null;//record The state of the Nodeunsi gned int Rank[maxhufflen]; Node *tree = null, *base = NULL, *left = NULL, *right = NULL; Node *start = null, *end = null, *last = null;//start:the First (min weight) node of 2*r,end:the last (max weight) node of 2 *r,last:the last node of array. Node *node = NULL; hufftable huffcode[maxsymbols];float bitspersymbols = 0.0;int WeightSum = 0;int sortindex[maxsymbols];int X = (Symbols-1) <<maxhufflen;//avoid float calculationint Minwidth,r,weight;int r_num = 0;if (Symbols > (1<<maxhufflen)) {printf ("Symbols > (1<<maxhufflen) \ n"); return-1;} for (i=0;i<maxsymbols;i++) {sortindex[i] = i;} Freqsort (Freq,sortindex,symbols);//sortquicksort (freq,sortindex,0,symbols-1);//sortfor (I=0;i<Symbols;i++) {WeightSum + = Freq[i];} Tree = (node *) malloc (symbols*maxhufflen*2*sizeof (node)); memset (tree,0,symbols*maxhufflen*2*sizeof (node));//2:for The Optimizeflag = (unsigned char*) malloc (maxhufflen*symbols*sizeof (unsigned char)); Memset (flag,0x01,maxhufflen* symbols*sizeof (unsigned char))//mark every node 1memset (huffcode,0,sizeof (Huffcode)); for (i=0;i<maxhufflen;i++) {for (j=0;j<symbols;j++) {tree[i*symbols+j].depth = I;tree[i*symbols+j].index = J;tree[i*symbols+j].width = 1< <i;//avoid float calculationtree[i*symbols+j].weight = Freq[j];}} Start codebase = tree; Last = Tree+maxhufflen*symbols-1;while (x>0) {minwidth = Getsmallestterm (X); r = base->width;if (r > MinWidth) {// There is no optimal solution.return-2;} else if (r = = minwidth) {X-= minwidth;base++;} Else{//merge the smallest width and insert it into the original Arrayif (R < (1<<)) {start = MaxHuffLen-1 _num = 1;//find start and Endwhile (Start->width < 2*r && start <= last) {R_num++;start++;} End = Start;while (End->width = = 2*r && End <= last) {end++;} End--;//move back the (>=2*r) Width Nodenode = Last;r_num = r_num/2;while (node >= start) {* (node+r_num) = *node;node-- ;} Package and Mergenode = Start;start = start + R_num;end = end + R_num;for (i=0;i<r_num;i++) {left = Base;base++;right = Base;base++;weight = Left->weight + right->weight;while (start <= end && start->weight <= weight) { *node = *start;start++;node++;} Node->weight = Weight;node->width = 2*r;node->left = Left;node->right = right;node++;} if (Base->width = = r) {//if r_num is odd,remove the last R (width) Node.removenodemark (base,flag,symbols); base++;} Last + = R_num;} ELSE{//R >= (1<< (MaxHuffLen-1)) while (Base->width = r) {left = Base;weight = Base->weight;if ((* (base+1)) . width = = r) {Base++;right = base;weight + = base->weight;base++; last++; Last->weight = weight; Last->width = 2*r; Last->left = left; Last->right = right;} Else{remOvenodemark (base,flag,symbols); base++;}}} }//output the Huffcodegeneratehuffmancode (huffcode,flag,maxhufflen,symbols,sortindex);//print HuffCodefor (i=0;i <symbols;i++) {printf ("%03d weight:%04d Code:", Huffcode[i].index,freq[i]); Printhuffcode (Huffcode[i]);p rintf ("\tcodelen:%02d", Huffcode[i].len);p rintf ("\ n");} Bitspersymbols = Bitspersymbol (huffcode,freq,symbols,weightsum);p rintf ("Average code length:%f bits/symbol.\n", Bitspersymbols); free (tree); tree = Null;free (Flag); Flag = Null;return 0;} #include <time.h>int main () {//int freq[maxsymbols] = {1,25,3,4,9,6,4,6,26,15,234,4578};//weight is not zero. int F Req[maxsymbols] = {10,6,2,1,1};//weight is not zero. Genlenlimitedopthuffcode (freq,5);//5,12 return 0;}
The output results are as follows:
Watermark/2/text/ahr0cdovl2jsb2cuy3nkbi5uzxqvchltcxe=/font/5a6l5l2t/fontsize/400/fill/i0jbqkfcma==/dissolve/70 /gravity/southeast ">
Optimal Huffman coding for constrained length based on binary tree and array