最优前缀码


问题

最优前缀编码

解析

二元前缀码:任何字符的代码不能作为其它字符代码的前缀.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