前段时间写的哈夫曼树的代码,拿出来和大家分享下
#include<stdio.h>
#include<stdlib.h>typedef struct node{
int weight;
int parent;
int left;
int right;
int word;
int cnt;
}huffnode; //哈弗曼树的节点
typedef struct{
int weight;
char word1;
}leafweight; //存放从文章中得到的叶子节点的权值和字符
typedef struct {
char ch;
int dic[100];
int end;
}Dic; //编码的数据字典
Dic dictionary[24];
int code[10000000]; //存放哈弗曼编码
int END=0; //编码的长度
void select(huffnode **f,int t,int *k1v,int *k2v) //查找权值最小的两个叶子结点
{
int j,k1,k2;
for(k1=0;f[k1]->parent!=-1;k1++);
for(k2=k1+1;f[k2]->parent!=-1;k2++);
for(j=k2;j<t;j++)
{
if(f[j]->parent==-1)
{
if(f[j]->weight<f[k1]->weight){k2=k1;k1=j;}
else if(f[j]->weight<f[k2]->weight) k2=j;
}
}
*k1v=k1;
*k2v=k2;
}
int CreatHuffmanTree(huffnode **f,int n)
{
int k1,k2,i,j,t=n;
huffnode *p;
for(i=0;i<n-1;i++)
{
select(f,t,&k1,&k2); //查找权值最小的两个叶子节点
p=(huffnode *)malloc(sizeof(huffnode));
p->weight=f[k1]->weight+f[k2]->weight;
p->left=k1;
p->right=k2;
p->parent=-1;
f[k1]->parent=t;
f[k2]->parent=t;
f[t++]=p;
}
return t;
}
void Code(huffnode **f,int n) //为每个叶子结点编码
{
int i,j,k,t,cnt;
for(i=0;i<n;i++)
{
k=i;
while(f[k]->parent!=-1) //查找双亲
{
t=f[k]->parent;
f[i]->cnt=f[i]->cnt*2+!(f[t]->left==k);
k=t;
}
}
}
void getdictionary(huffnode **f,int n,int end) //得到编码的数据字典并输出
{
int i,j,end1,t,k;
for(i=0;i<n;i++)
{
k=0;
end1=end-1;
t=f[i]->cnt;
dictionary[i].ch=f[i]->word;
printf("'%c':",f[i]->word);
while(f[end1]->left!=-1&&f[end1]->right!=-1){
printf("%d",t%2);
dictionary[i].dic[k++]=t%2;
if(t%2) end1=f[end1]->right;
else end1=f[end1]->left;
t/=2;
}
printf(" ");
dictionary[i].end=k;
}
printf("\n");
}
void IntputLeaf(huffnode **f,leafweight s[],int n) //输入每个叶子结点信息
{
int i;
for(int i=0;i<n;i++)
{
f[i]=(huffnode *)malloc(sizeof(huffnode));
f[i]->weight=s[i].weight;f[i]->word=s[i].word1;
f[i]->left=f[i]->right=f[i]->parent=-1;
f[i]->cnt=0;
}
}
void PrintHufftree(huffnode **f,int t) //输出全部节点
{ int i;
for(i=0;i<t;i++)
{
printf("第%d个结点信息: %d %c %d %d %d %d\n",i+1,f[i]->weight,f[i]->word,f[i]->left,f[i]->right,f[i]->parent,f[i]->cnt);
}
}
int getleaf(leafweight *s,char *word) //从文章中得到叶子节点的权值和字符
{
int i,j,t,k=0;
for(i=0;word[i]!=0;i++)
{
for(j=0;j<k;j++)
{
if(word[i]==s[j].word1) {
s[j].weight++;break;}
}
if(j==k)
{
s[k].word1=word[i];s[k++].weight=1;}
}
return k;
}
void printcode(char *word,Dic *dictory,int cnt) //输出编码并存放编码
{
printf("该文章的编码:");
for(int i=0;word[i]!=0;i++)
{
for(int j=0;j<cnt;j++)
{
int t=0;
if(word[i]==dictory[j].ch){
while(t<dictory[j].end)
{
code[END++]=dictory[j].dic[t]; //存放编码
printf("%d",dictory[j].dic[t++]);
}
break;
}
}
}
printf("\n");
}
void decode(huffnode **f,int t) //解码
{
printf("解码为:");
for(int i=0,j=t-1;i<END;i++)
{
if(code[i]) j=f[j]->right;
else j=f[j]->left;
if(f[j]->left==-1&&f[j]->right==-1)
{
printf("%c",f[j]->word);
j=t-1;
}
}
}
int main (void)
{
huffnode **f;
leafweight *s; //存放从文章中得到的权值和字符的数组的指针
int t,n;
char word[10000];
printf("请输入文章:");
gets(word);
s=(leafweight *)malloc(sizeof(leafweight)*24);
n=getleaf(s,word); //从文章中得到叶子的权值和字符
f=(huffnode **)malloc(sizeof(huffnode *)*(2*n-1));
IntputLeaf(f,s,n); // 输入叶子信息
t=CreatHuffmanTree(f,n); // 创建哈弗曼树
Code(f,n); // 为哈弗曼树编码用位存储
getdictionary(f,n,t); // 得到字符编码的数据字典
printcode(word,dictionary,n); // 输出该文章的编码
PrintHufftree(f,t); //输出哈弗曼树的每个节点
decode(f,t); //解码
return 0;
}