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