最優前綴碼


問題

最優前綴編碼

解析

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM