poj 1521_huffmanb code

题目描述:

输入字符串,求用赫夫曼编码能得到的最好的字符编码方式,令总长度最小。求最小的长度。

解题思路:

建结构记录权重(字符出现的频率),父节点,左右子节点标识(n个叶子节点拥有不同的权重)作为赫夫曼树的叶子点结构;建立赫夫曼树(开一个2*n-1大小的数组,建立一棵有n个叶子的赫夫曼树,每次合并两个节点记录总权值)后,递归求得总权值,即为总长度。

时间复杂度为O(n2),n为不同的节点数。

代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 100000
 
typedef struct{
        int weight;
        int parent, lc, rc;
}HTNode;

HTNode ht[N];
char str[N];
int sum1,sum, n, num[27], i,j, min, tmp1,tmp2;
double sum2;

void sum_weight(HTNode hn, int i)
{
   if(hn.lc == 0 && hn.rc == 0)
      sum += hn.weight*i;
   else
   {
       sum_weight(ht[hn.lc], i+1);
       sum_weight(ht[hn.rc], i+1);
   }
}

main()
{
   scanf("%s", str);
   while(strcmp(str, "END") != 0)
   {
      n = strlen(str);
      sum1 = n*8;
      for(i=0;i<=26;i++)
         num[i] = 0;
      for(i=0;i<n;i++)
      {
         if(str[i] == '_')
            num[26]++;
         else
            num[str[i]-'A']++;
      }
      j=0;
      for(i=0;i<27;i++)
      {
         if(num[i]!=0)
         {
            ht[j].weight = num[i];
            ht[j].parent = 0;
            ht[j].lc = 0;
            ht[j].rc = 0;
            j++;
         }
      }
      n = j; 
      //create hurff tree
      for(i=n; i<2*n-1; i++)
      {
         //select less two nodes
         min = 10000;
         for(j=0;j<i;j++)
         {
            if(ht[j].parent == 0 && ht[j].weight < min)
            {
               tmp1 = j;
               min = ht[j].weight;
            }
         }
         min = 10000;
         for(j=0;j<i;j++)
         {
            if(ht[j].parent == 0 && ht[j].weight < min && j!= tmp1)
            {
               tmp2 = j;
               min = ht[j].weight;
            }
         }
         //更改节点信息:
         ht[tmp1].parent = i;
         ht[tmp2].parent = i;
         ht[i].lc = tmp1;
         ht[i].rc = tmp2;
         ht[i].weight = ht[tmp1].weight + ht[tmp2].weight;
         ht[i].parent = 0;
      }
      sum = 0;
      //calculate the sum of weight, root  is in 2*n-2
      if(n == 1)
         sum = strlen(str);
      else
         sum_weight(ht[2*n-2],0);
      sum2 = (double)((double)sum1/(double)sum);
      printf("%d %d %.1f\n",sum1, sum,sum2);
     
      scanf("%s", str);
   }
   //system("pause");
   return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值