問題
最優前綴編碼
解析
二元前綴碼:任何字符的代碼不能作為其它字符代碼的前綴.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; }
