最优前缀码

1.问题

由哈夫曼树求得的编码为最优前缀码。每个叶子表示的字符的编码,就是从根到叶子的路径上的标号依次相连所形成的编码,显然这就是该字符的最优前缀码。所谓前缀码是指,对字符集进行编码时,要求字符集中任一字符的编码都不是其它字符的编码的前缀,比如常见的等长编码就是前缀码。所谓最优前缀码是指,平均码长或文件总长最小的前缀编码称为最优的前缀码(这里的平均码长相当于码长的期望值)。

2.解析

最优前缀码_第1张图片

3.设计

void SelectMin(HuffmanTree T,int k,int *p1,int *p2){
    //在前k个结点中选择权值最小和次小的根结点,其序号分别为p1和p2
    temp x[m];              //x向量为temp类型的向量
    int i,j;
    for(i=0,j=0;i<=k;i++){  //寻找最小和次小根节点的过程
        if(T[i].parent==-1){//如果是根节点,则进行如下操作
            x[j].id=i;      //将该根节点的序号赋值给x
            x[j].weight=T[i].weight;//将该根节点的权值赋值给x
            j++;            //x向量的指针后移一位
        }
    }
    sort(x,x+j,cmp);        //对x按照权值从小到大排序
    //排序后的x向量的第一和第二个位置中存储的id是所找的根节点的序号值
    *p1=x[0].id;
    *p2=x[1].id;
}

void CharSetHuffmanEncoding(HuffmanTree T,HuffmanCode H){
    //根据哈夫曼树T求哈夫曼编码表H
    int c,p;//c和p分别指示T中孩子和双亲的位置
    char cd[n+1];//临时存放编码
    int start;//指示编码在cd中的起始位置
    cd[n]='\0';//编码结束符
    getchar();
    for(int i=0;i<n;i++){//依次求叶子T[i]的编码
        H[i].ch=getchar();//读入叶子T[i]对应的字符
        start=n;//编码起始位置的初值
        c=i;//从叶子T[i]开始上溯
        while((p=T[c].parent)>=0){//直至上溯到T[c]是树根为止
            //若T[c]是T[p]的左孩子,则生成代码0;否则生成代码1
            if(T[p].lchild==c)
                cd[--start]='0';
            else
                cd[--start]='1';
            c=p;//继续上溯
        }
        strcpy(H[i].bits,&cd[start]);//复制编码位串
    }
}

4.分析

O(nlogn)频率排序;for 循环 O(n),插入操作 O(logn),算法时间复杂度是 O(nlogn)度 O(nlogn+n)=O(nlogn)

5.源码

GitHub

你可能感兴趣的:(最优前缀码)