1.问题
给定字符集C=[x1,x2,…,xn]和每个字的频率f(xi) ,求关于C的一个最优前缀码解析
2.设计
哈夫曼算法
//根据哈夫曼树求曼编码表
int c, p;
char cd[n + 1]
//临时存放编码
int start;
//指示编码在cd中的起始位置
cd[n] = ‘\0’;
//编码结束符
getchar();
for (int i = 0; i < n; i++) {
//依次求叶子T[i]的编码
H[i].ch = getchar();
start = n;
c = i;//从叶子T[i]
while ((p = T[c].parent) >= 0) {
if (T[p].lchild == c)
cd[--start] = '0';
else
cd[--start] = '1';
c = p;
}
strcpy_s(H[i].bits, &cd[start]);
}
}
3.分析
时间复杂度为O(nlogn)
4.源码
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
int ww;
int ld,lr,lp;
}HTNode,*HuffmanTree;
typedef char **HuffmanCode;
HuffmanTree HC;
HuffmanTree HT;
int aa;
int bb;
void SelectMin(HuffmanTree tree,int n){
int minn=1;
for(int i=1;i<=n;i++){
if(tree[i].lp0){
minn=i;
break;
}
}
for(int i=1;i<=n;i++){
if(tree[i].lp0&&tree[i].ww<tree[minn].ww){
minn=i;
}
}
aa=minn;
for(int i=1;i<=n;i++){
if(tree[i].lp==0&&i!=aa){
minn=i;
break;
}
} //找出最小值
for(int i=1;i<=n;i++){
if(tree[i].lp==0&&tree[i].ww<tree[minn].ww&&i!=aa){//找出第二个最小值
minn=i;
}
}
bb=minn;
// printf(“aa:%d bb:%d\n”,aa,bb);
}
void Huffman(HuffmanTree tree,int w,int n){//哈夫曼编码
int m=2n-1;//哈夫曼树的节点数
tree=(HuffmanTree)malloc((m+1)*sizeof(HTNode));//申请节点
for(int i=1;i<=m;i++){//初始化树
tree[i].ld=0;
tree[i].lr=0;
tree[i].lp=0;
if(i<=n){//设置每个叶子节点的权值
tree[i].ww=w[i];
}
else{
tree[i].ww=0;
}
}
for(int i=n+1;i<=m;i++){
//构成了一颗哈夫曼树
SelectMin(tree,i-1);
tree[aa].lp=i;
tree[bb].lp=i;
tree[i].ld=aa;
tree[i].lr=bb;
tree[i].ww=tree[aa].ww+tree[bb].ww;
}
HC=(HuffmanTree)malloc((n+1)*(sizeof(char *)));
char *cd;
cd=(char *)malloc(n*sizeof(char));
cd[n-1]='\0';
//编码结束符为'\0'
int start;
for(int i=1;i<=n;i++){
start=n-1;
for(int j=i,f=tree[i].lp;f!=0;j=f,f=tree[f].lp){
//逆向求哈夫曼编码
if(tree[f].ld==j) cd[--start]='0';
else cd[--start]='1';
}
HC[i]=(char *)malloc((n-start)*sizeof(char));
strcpy(HC[i],&cd[start]);
}
free(cd);
}
int main(int argc, const char * argv[]) {
int n=10;
int w[200]={0,30,40,20,10,5,15,10,45,20,60};
Huffman(HT, w, n);
for(int k=1;k<n;k++){
printf("%s\n",HC[k]);
}
printf("\n");
return 0;
}