- 论坛徽章:
- 0
|
从每个叶子节点往根遍历不就生成了 huffman code 了嘛
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct{
unsigned long weight;
int parent, lchild, rchild;
} HTNode, *HuffmanTree;
typedef char** HuffmanCode;
//HuffmanCode HC;
void Select(HuffmanTree HT, int n, int *s1, int *s2);
struct wandc{
int w;
int c;
char *cd;
};
void HuffmanCoding(struct wandc *wc, int n)
{
int i;
if( n<=1 ) return;
int m = 2*n - 1;
HuffmanTree p;
HuffmanTree HT = (HuffmanTree)malloc((m+1)*sizeof(HTNode));
memset(HT, 0, sizeof(HTNode) * (m+1));
for( p=HT,i=1; i<=n; ++i,++p )
{
HT[i].weight = wc[i].w;
}
int s1=0, s2=0;
for( i=n+1; i<=m; ++i )
{
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;
}
//HC = (HuffmanCode)malloc((n+1)*sizeof(char*));
char *cd = (char*)malloc(n*sizeof(char));
cd[n-1] = 0;
int start;
unsigned long f;
for( i=1; i<=n; ++i )
{
start = n - 1;
int c;
for( c=i, f=HT[i].parent; f!=0; c=f, f=HT[f].parent )
{
if( HT[f].lchild == c ) cd[--start] = '0';
else cd[--start] = '1';
}
wc[i].cd = (char*)malloc((n-start)*sizeof(char));
strcpy(wc[i].cd, &cd[start]);
}
free( HT );
}
void Select(HuffmanTree HT, int n, int *s1, int *s2)
{
int i;
HT[0].weight = (unsigned long)(-1l);
*s1 = *s2 = 0;
for( i=1; i<=n; i++ )
if( HT[i].parent == 0 )
{
if( HT[i].weight < HT[*s1].weight )
{
*s2 = *s1;
*s1 = i;
}
else if( HT[i].weight < HT[*s2].weight )
{
*s2 = i;
}
}
}
int main()
{
char buf[128];
fgets(buf, sizeof(buf), stdin);
int len = strlen(buf);
buf[len-1] = 0;
len--;
unsigned long weight[256];
memset( weight, 0, sizeof(weight));
int i;
for(i=0; i<len; i++)
{
weight[buf[i]]++;
}
int n = 0;
for(i=0; i<256; i++)
if( weight[i] )
n++;
printf("num of char = %d\n", n);
struct wandc *array = (struct wandc*)malloc(sizeof(struct wandc)*(n+1));
int j =1;
for(i=0; i<256; i++)
if( weight[i] )
{
array[j].w = weight[i];
array[j].c = i;
j++;
}
HuffmanCoding( array, n );
printf("\n");
for(i=1; i<=n; i++)
printf("char=%c,w=%d: %s\n", array[i].c,array[i].w,array[i].cd);
printf("\n");
for(i=0; i<len; i++)
{
for(j=0; j<n; j++)
if( buf[i] == array[j].c )
break;
printf("%s",array[j].cd);
}
printf("\n");
return 0;
} |
|