c
,字符频率集w
如下:char c[]={a,b,c,d,e,f};
int w[]={8,3,4,6,5,5};
10010001101111000
能译出正确的字符序列abdefad
构造一棵Huffman树
typedef struct
{ char data; //节点值
double weight ; //权值域
int parent , lchild , rchild ;
} HTNode ;
CreateHT
c
和字符频率集w
定义初始数组变量如下:int w[]={8,3,4,6,5,5};
char c[]={'a','b','c','d','e','f'};
int nums=6;
HTNode HT[2*nums-1]; //哈夫曼树结点数组
data
和weight
至HT
数组如下:for(int i=0;i<nums;i++)
{
HT[i].weight=w[i];
HT[i].data=c[i];
}
CreateHT(HT,nums); //创建哈夫曼树
求Huffman编码
#define N 10 //N的值大于n(想想为什么?)
typedef struct
{
char cd[N]; //存放当前节点的哈夫曼码
int start; //存放哈夫曼码在cd中的起始位置
} HCode; //哈夫曼编码结点类型
CreateHCode
HCode HC[nums];
CreateHCode(HT, HC, nums);
对输入信号进行译码
EnHCode
code
及显示code
信息如下:char code[]="10010001101111000"; //abdefad
printf("\n\n待译码信号为:");
for(int k=0;code[k]!='\0';k++)
{
printf("%c",code[k]);
}
DeCode
用于保存译码后的字符串如下:char DeCode[20]; //保存译码后的字符串
if( EnHCode(code,HT,DeCode,nums) )
{
printf("\n\n成功译码!");
printf("\n译码后:");
int i=0;
while(DeCode[i] != '\0')
{
printf("%c",DeCode[i]);
i++;
}
}
else
{
printf("\n\n代码错误!");
}
完整代码如下:
#include
#include
#define N 10
typedef struct
{
char data; //节点值
double weight; //权值域
int parent, lchild, rchild;
} HTNode;
typedef struct
{
char cd[N]; //存放当前节点的哈夫曼码
int start; //存放哈夫曼码在cd中的起始位置
}HCode; //哈夫曼编码结点类型
void CreateHT(HTNode ht[],int n)
{ int i,j,k,lnode,rnode; float min1,min2;
for (i=0;i<2*n-1;i++)
ht[i].parent = ht[i].lchild = ht[i].rchild = -1;
for (i=n; i<2*n-1; i++)
{ min1 = min2 = 32767;
lnode = rnode = -1;
for (k=0; k<=i-1; k++)
if (ht[k].parent == -1) //未构造二叉树的结点中查找
{ if (ht[k].weight < min1) //找最小的weight
{ min2 = min1;
rnode = lnode;
min1 = ht[k].weight;
lnode = k;
} else if (ht[k].weight < min2) //找次小的weight
{ min2 = ht[k].weight;
rnode = k;
}
} //if
ht[lnode].parent = i;
ht[rnode].parent = i;
ht[i].weight = ht[lnode].weight + ht[rnode].weight;
ht[i].lchild = lnode;
ht[i].rchild = rnode;
}
}
void initHT(HTNode ht[], int nums, int w[], char c[]) {
for(int i=0;i<nums;i++)
{
ht[i].weight=w[i];
ht[i].data=c[i];
}
}
void CreateHCode(HTNode ht[], HCode hcd[], int n)
{ int i,f,c; HCode hc;
for (i=0; i<n; i++)
{ hc.start = n;
c = i ;
f = ht[i].parent;
while ( f != -1)
{ if( ht[f].lchild == c )
hc.cd[hc.start--] = '0';
else
hc.cd[hc.start--] = '1';
c=f; f=ht[f].parent;
}
hc.start++;
hcd[i]=hc;
}
}
void printHT(HTNode ht[], int nums, char c[]) {
for(int i=0;i<2*nums-1;i++)
{
if(i<=5){
ht[i].data=c[i];
}else
ht[i].data='\0';
printf("Node %-2d: data=%-2c, weight=%-2.0f, parent=%-2d, lchild=%-2d, rchild=%-2d\n", i, ht[i].data, ht[i].weight, ht[i].parent, ht[i].lchild, ht[i].rchild);
}
}
void printHCode(HTNode ht[], HCode hcd[], int nums) {
for(int i=0;i<nums;i++)
{
printf("Node %-2d: data=%-2c, Code=%s\n", i, ht[i].data,&hcd[i].cd[hcd[i].start]);
}
}
int EnHCode(char code[], HTNode ht[], char DeCode[], int nums) {
int i = 0, j = 0;
while(code[i] != '\0') {
if(code[i] == '0') {
j = ht[j].lchild;
} else if(code[i] == '1') {
j = ht[j].rchild;
} else {
return 0;
}
if(ht[j].lchild == -1 && ht[j].rchild == -1) {
DeCode[i] = ht[j].data;
j = 0;
}
i++;
}
DeCode[i] = '\0';
return 1;
}
int main()
{
int w[] = {6, 3, 4, 8, 5, 5};
char c[] = {'a', 'b', 'c', 'd', 'e', 'f'};
int nums = 6;
HTNode HT[2*nums-1];
HCode HC[nums];
initHT(HT, nums, w, c);
CreateHT(HT,nums);
printHT(HT, nums,c);
printf("=============================================================\n");
CreateHCode(HT, HC, nums);
printHCode(HT, HC, nums);
char code[]="10010001101111000"; //abdefad
printf("\n\n待译码信号为:");
for(int k=0;code[k]!='\0';k++)
{
printf("%c",code[k]);
}
printf("\n");
char DeCode[20]; //保存译码后的字符串
if( EnHCode(code,HT,DeCode,nums) )
{
printf("\n\n成功译码!");
printf("\n译码后:");
int i=0;
while(DeCode[i] != '\0')
{
printf("%c",DeCode[i]);
i++;
}
}
else
{
printf("\n\n代码错误!");
}
return 0;
}
【实验总结(个人心得)】
深入地了解了Huffman编码的原理和实现方法,实现了构造一棵Huffman树,输出树各节点的值,输出各字符对应的Huffman编码。但是,发现对于输入信号进行译码这部分内容实验失败。这可能是因为Huffman树构造或Huffman编码运算存在问题,导致无法正确地进行译码。