哈夫曼编码
哈夫曼编码(Huffman Coding),又称霍夫曼编码,是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种。Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长度最短的码字,有时称之为最佳编码,一般就叫做Huffman编码(有时也称为霍夫曼编码)。
发展历史
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <math.h>
5 #define M 100
6 typedef struct Fano_Node
7 {
8 char ch;
9 float weight;
10 }FanoNode[M];
11 typedef struct node
12 {
13 int start;
14 int end;
15 struct node *next;
16 }LinkQueueNode;
17 typedef struct
18 {
19 LinkQueueNode *front;
20 LinkQueueNode *rear;
21 }LinkQueue;
22 //建立队列
23 void EnterQueue(LinkQueue *q,int s,int e)
24 {
25 LinkQueueNode *NewNode;
26 //生成新节点
27 NewNode=(LinkQueueNode*)malloc(sizeof( LinkQueueNode ));
28 if(NewNode!=NULL)
29 {
30 NewNode->start=s;
31 NewNode->end=e;
32 NewNode->next=NULL;
33 q->rear->next=NewNode;
34 q->rear=NewNode;
35 }
36 else
37 {
38 printf("Error!");
39 exit(-1);
40 }
41 }
42 //按权分组
43 void Divide(FanoNode f,int s,int *m,int e)
44 {
45 int i;
46 float sum,sum1;
47 sum=0;
48 for(i=s;i<=e;i++)
49 sum+=f[i].weight;//
50 *m=s;
51 sum1=0;
52 for(i=s;i<e;i++)
53 {
54 sum1+=f[i].weight;
55 *m=fabs(sum-2*sum1)>fabs(sum-2*sum1-2*f[i+1].weight)?(i+1):*m;
56 if(*m==i) break;
57 }
58 }
59 void main()
60 {
61 int i,j,n,max,m,h[M];
62 int sta,end;
63 float w;
64 char c,fc[M][M];
65 FanoNode FN;
66 LinkQueueNode *p;
67 LinkQueue *Q;
68 //初始化队Q
69 Q=(LinkQueue *)malloc(sizeof(LinkQueue));
70 Q->front=(LinkQueueNode*)malloc(sizeof(LinkQueueNode));
71 Q->rear=Q->front;
72 Q->front->next=NULL;
73 printf("\t***FanoCoding***\n");
74 printf("Please input the number of node:");
75 //输入信息
76 scanf("%d",&n);
77 //超过定义M,退出
78 if(n>=M)
79 {
80 printf(">=%d",M);
81 exit(-1);
82 }
83 i=1; //从第二个元素开始录入
84 while(i<=n)
85 {
86 printf("%d weight and node:",i);
87 scanf("%f %c",&FN[i].weight,&FN[i].ch);
88 for(j=1;j<i;j++)
89 {
90 if(FN[i].ch==FN[j].ch)//查找重复
91 {
92 printf("Same node!!!\n"); break;
93 }
94 }
95 if(i==j)
96 i++;
97 }
98 //排序(降序)
99 for(i=1;i<=n;i++)
100 {
101 max=i+1;
102 for(j=max;j<=n;j++)
103 max=FN[max].weight<FN[j].weight?j:max;
104 if(FN[i].weight<FN[max].weight)
105 {
106 w=FN[i].weight;
107 FN[i].weight=FN[max].weight;
108 FN[max].weight=w;
109 c=FN[i].ch;
110 FN[i].ch=FN[max].ch;
111 FN[max].ch=c;
112 }
113 }
114 for(i=1;i<=n;i++) //初始化h
115 h[i]=0;
116 EnterQueue(Q,1,n); //1和n进队
117 while(Q->front->next!=NULL)
118 {
119 p=Q->front->next; //出队
120 Q->front->next=p->next;
121 if(p==Q->rear)
122 Q->rear=Q->front;
123 sta=p->start;
124 end=p->end;
125 free(p);
126 Divide(FN,sta,&m,end); /*按权分组*/
127 for(i=sta;i<=m;i++)
128 {
129 fc[i][h[i]]='0';
130 ++h[i];
131 }
132 if(sta!=m)
133 EnterQueue(Q,sta,m);
134 else
135 fc[sta][h[sta]]='\0';
136 for(i=m+1;i<=end;i++)
137 {
138 fc[i][h[i]]='1';
139 ++h[i];
140 }
141 if(m==sta&&(m+1)==end)
142 //如果分组后首元素的下标与中间元素的相等,
143 //并且和最后元素的下标相差为1,则编码码字字符串结束
144 {
145 fc[m][h[m]]='\0';
146 fc[end][h[end]]='\0';
147 }
148 else
149 EnterQueue(Q,m+1,end);
150 }
151 for(i=1;i<=n;i++) /*打印编码信息*/
152 {
153 printf("%c:",FN[i].ch);
154 printf("%s\n",fc[i]);
155 }
156 system("pause");
157 }