#include<stdio.h>
#include<stdlib.h>
#define max 100
struct BTreeNode
{
char data;//字符信息
int weight;//权重
struct BTreeNode* left;
struct BTreeNode* right;
};
struct Code//存储每个字符的编码
{
int len;//编码长度
char data;//存储字符
int *code;//定义一个可变数组,返回头指针,每一位存储一个编码信息
struct Code *next;
};
struct BTreeNode* CreateHuffman(int a[],char p[] ,int n)//创建huffman树,数组a传入权重,数组p传入待编码字符信息,n待编码字符个数
{
int i, j;
struct BTreeNode **b, *q;
b = malloc(n*sizeof(struct BTreeNode));
for (i = 0; i < n; i++)
{
b[i] = malloc(sizeof(struct BTreeNode));
b[i]->weight=a[i];
b[i]->data=p[i];
b[i]->left = b[i]->right = NULL;
}
for (i = 1; i < n; i++)
{
//k1表示森林中具有最小权值的树根结点的下标,k2为次最小的下标
int k1 = -1, k2;
for (j = 0; j < n; j++)//让k1初始指向森林中第一棵树,k2指向第二棵
{
if (b[j] != NULL && k1 == -1)
{
k1 = j;
continue;
}
if (b[j] != NULL)
{
k2 = j;
break;
}
}
for (j = k2; j < n; j++)//从当前森林中求出最小权值树和次最小
{
if (b[j] != NULL)
{
if (b[j]->weight < b[k1]->weight)
{
k2 = k1;
k1 = j;
}
else if (b[j]->weight < b[k2]->weight)
k2 = j;
}
}
//由最小权值树和次最小权值树建立一棵新树,q指向树根结点
q = malloc(sizeof(struct BTreeNode));
q->weight = b[k1]->weight + b[k2]->weight;
q->data='#';
q->left = b[k1];
q->right = b[k2];
b[k1] = q;//将指向新树的指针赋给b指针数组中k1位置
b[k2] = NULL;//k2位置为空
}
free(b);
return q;
}
struct Code* HuffManCoding(struct BTreeNode* FBT, int len)//编码
{
static struct Code *head;
static int a[10];//静态数组,存储编码信息
if (FBT != NULL)
{
if (FBT->left == NULL && FBT->right == NULL)
{
int i;
struct Code *p;
int *code;
p=(struct Code*)malloc(sizeof(struct Code));//申请一个节点
code=(int *)malloc(len*sizeof(int));//申请可变数组,用于存储编码信息
p->data=FBT->data;
p->len=len;
printf("字母:%c,权值:%d,编码:",FBT->data,FBT->weight);
for (i = 0; i < len; i++)
{
printf("%d",a[i]);
code[i]=a[i];
}
p->code=code;
if (head==NULL)//节点之间的链接
{
p->next=NULL;
head=p;
}
else
{
p->next=head->next;
head->next=p;
}
printf("\n");
}
else
{
a[len] = 0;
HuffManCoding(FBT->left, len + 1);
a[len] = 1;
HuffManCoding(FBT->right, len + 1);
}
}
return head;
}
void find(struct Code *head,char x)//查找字符x,输出字符编码。head存储编码信息的头指针,x待查找字符
{
int i;
while (head)
{
if (head->data==x)
{
for (i=0;i<head->len;i++)
printf("%d",head->code[i]);
return ;
}
else
head=head->next;
}
}
int main()
{
struct Code *head;
int n=0,k=0,t=1,i,j,weight[max]={0},isread[max]={0};//weight存储权重
struct BTreeNode* fbt;
char S[max],ch,data[max];//S存储字符串,data存储带编码字符
printf("请输入字符串:");
while ((ch=getchar())!='\n')
S[n++]=ch;
for (i=0;i<n;t=1,i++)
{
if (isread[i]==1)
continue;
ch=S[i];
isread[i]=1;
for (j=i+1;j<n;j++)
{
if (ch==S[j])
{
isread[j]=1;
t++;
}
}
weight[k]=t;
data[k++]=ch;
}
fbt = CreateHuffman(weight,data,k);
printf("树中每个叶子结点的哈夫曼编码:\n");
head=HuffManCoding(fbt,0);
printf("字符串编码为:");
for (i=0;i<n;i++)
{
find(head,S[i]);
}
return 0;
}