关于哈夫曼树


前段时间写的哈夫曼树的代码,拿出来和大家分享下

#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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值