问题
最优前缀编码
解析
二元前缀码:任何字符的代码不能作为其它字符代码的前缀.eg.Q={001,00,010,01}不是二元前缀代码,如序列0100001会产生歧义
设C={x1,x2,…,xn}是n个字符的集合,f(xi)为xi出现的频率,d(xi)为xi的码长,i=1,2,…,n.
存储一个字符的平均二进制位数(码数):
B=∑i=1nf(xi)d(xi)
每个二元前缀码对应一棵二叉树,树叶代表码字,树叶的深度表示码长,平均二进制位数相当于这棵树在给定频率下的平均深度,也称为这棵树的权
对同一组频率可以构造出不同的二叉树,对应的平均二进制位数也不同。占用位数越少的压缩效率越高,即每个码字平均使用二进制位数最少的前缀码,称为最优二元前缀码
如果叶片数n=2k,且每个码字的频率是1/n,那么这棵树应是一颗均衡的二叉树
设计
Huffman算法:
输入:C={x1,x2,…,xn}字符集,每个字符的频率f(xi),i=1,2,…,n.
输出:Q
1.n<-|C|
2.Q<-C //按频率递增构成队列 Q
3.for i<-1 to n-1 do
4. z<-Allocate-Node()
5. z.left<-Q中最小元 //取出Q中最小元作为z的左儿子
6. z.right<-Q中最小元 //取出Q中最小元作为z的右儿子
7. f(z)<-f(x)+f(y)
8. Insert(Q,z)
9.return Q
代码
#include<stdio.h> #include<stdlib.h> #include<math.h> typedef struct tree *PointTree; typedef PointTree Tree; void merge(int start,int end, int *array); Tree createTree(int number); Tree freeTree(Tree T); Tree addTree(Tree left,Tree right,Tree T); void PrintfHuffman(Tree T, char *array, int num); void PrintHuffman(Tree T, char *array, int num, int flag); Tree HUffman(int sum,int *array); struct tree{ int number; PointTree Left; PointTree Right; }; void merge(int start,int end, int *array){ int middle = (start+end)/2; int sum = end -start+1; int i,k,j; if(start >= end){ return; } else{ merge(start,middle,array); merge(middle+1,end,array); } int iArray[sum]; i = start; j = middle+1; k = 0; while(i<=middle && j<=end){ if(array[i] < array[j]){ iArray[k++] = array[i++]; } else{ iArray[k++] = array[j++]; } } if(i > middle && j <=end){ while(j<=end){ iArray[k++] = array[j++]; } } else if(j>end && i<=middle){ while(i<=middle){ iArray[k++] = array[i++]; } } j = start; for(i=0;i<k;i++){ array[j++] = iArray[i]; } return; } Tree createTree(int number) { Tree T; T = malloc(sizeof(struct tree)); T->number = number; T->Left = NULL; T->Right = NULL; return T; } Tree freeTree(Tree T) { if(T ==NULL){ return NULL; } T->Right = freeTree(T->Right); T->Left = freeTree(T->Left); if(T->Right == NULL && T->Left == NULL){ free(T); return NULL; } } Tree addTree(Tree left,Tree right,Tree T) { if(left == NULL || right == NULL) { return NULL; } T = malloc(sizeof(struct tree)); T->number = left->number + right->number; T->Left = left; T->Right = right; return T; } void PrintfHuffman(Tree T, char *array, int num) { PrintHuffman(T->Left,array,num,0); PrintHuffman(T->Right,array,num,1); } void PrintHuffman(Tree T, char *array, int num, int flag){ char Array[40]; int i; for(i=0;i<num;i++){ Array[i] = array[i]; } if(flag == 1) { Array[num++] = '1'; printf("%c\n",Array[num-1]); } else{ Array[num++] = '0'; printf("%c\n",Array[num-1]); } if(T->Left == NULL && T->Right ==NULL) { Array[num] = '\0'; printf("%d:%s\n",T->number,Array); } else{ PrintHuffman(T->Left,Array,num,0); PrintHuffman(T->Right,Array,num,1); } } Tree HUffman(int sum,int *array){ int i; Tree T; int Flag=0; int sign1 =0,sign2=1; int data[10] = {10,10,20,20,40,60,80,90,30,50}; sum = 10; Tree tree[10]; merge(0,9,data); for(i=0;i<10;i++){ tree[i] = createTree(data[i]); printf("%d\n",tree[i]->number); } while(sign2 < 10){ if(Flag == 2) { if(tree[sign1] -> number <= tree[sign2] -> number && tree[sign1+1] -> number <= tree[sign2] -> number) { T= addTree(tree[sign1],tree[sign1+1],T); Flag = 1; //freeTree(tree[sign1]); //freeTree(tree[sign1+1]); tree[0] = T; sign2--; } else if(tree[sign1] -> number <= tree[sign1+1] -> number) { T = addTree(tree[sign1],tree[sign2],T); //freeTree(tree[sign1]); //freeTree(tree[sign2]); tree[sign1] = T; } else{ sign1++; T = addTree(tree[sign1],tree[sign2],T); //freeTree(tree[sign1]); //freeTree(tree[sign2]); tree[sign1] = T; sign1--; } } else{ if(sign2+1 >= 10){ break; } if(tree[sign2]->number <= tree[sign1] -> number && tree[sign2+1] -> number <= tree[sign1] -> number){ T = addTree(tree[sign2],tree[sign2+1],T); Flag = 2; //freeTree(tree[sign2]); //freeTree(tree[sign2+1]); tree[sign1+1] = T; sign2++; } else{ T = addTree(tree[sign1],tree[sign2],T); //freeTree(tree[sign1]); //freeTree(tree[sign2]); tree[sign1] = T; } } sign2++; } if(Flag == 2){ T= addTree(tree[sign1],tree[sign1+1],T); //freeTree(tree[sign1]); //freeTree(tree[sign1+1]); tree[0] = T; } else{ T = addTree(tree[sign1],tree[sign2],T); //freeTree(tree[sign1]); //freeTree(tree[sign2]); tree[0] = T; sign2++; } char Array[40]; printf("%d\n",tree[0]->Right->number); PrintfHuffman(tree[0],Array,0); } void main(){ int sum; int array[10]; HUffman(sum,array); return; }