Huffman树

要解决的问题是关于霍夫曼树的,题目在:

http://acm.hdu.edu.cn/showproblem.php?pid=1053

直接写代码吧,不得不说写得真的很复杂,调试了半天,出了好多错哈:

#include<cstdio>
#include<queue>
#include<cstring>
#include<string>

using namespace std;

const int R = 27;   // A~Z, _
const int MAXLEN = 100;
char str[MAXLEN];

class Item{
    public:
        char ch;
        int  freq;
        Item* left, *right;

        bool operator< (const Item i)const
        {
            return (this->freq > i.freq);
        }
        void clear()
        {
            ch = ' ';
            freq = 0;
            left = NULL;
            right = NULL;
        }

        Item(){}

        Item(char c, int f, Item* l, Item* r)
        {
            ch = c; freq = f;
            left = l; right = r;
        }
};
priority_queue<Item> pq;// to implement the huffman trie

string code;
string ch[R];           // for implementing a codeword table
Item item[R];


void clear()
{
    code.clear();

    while(!pq.empty())
        pq.pop();

    for(int i = 0; i < R; i++)
    {
        ch[i].clear();
        item[i].clear();
    }
}

void build_codetl(Item root)
{
    // only one node
    if(root.left == NULL && root.right == NULL)
    {
        if(root.ch != '_')
            ch[root.ch - 'A'] = "0";
        else
            ch[26] = "0";

        return;
    }
    else
        build_codetl(root, code, ch);
}

void build_codetl(Item node, string code, string ch[])
{
    if(node.left == NULL && node.right == NULL)
    {
        if(node.ch != '_')
            ch[node.ch - 'A'] = code;
        else
            ch[26] = code;

        return;
    }

    build_codetl(*(node.left), code + "0", ch);
    build_codetl(*(node.right), code + "1", ch);
}
int main()
{
    memset(str, 0, MAXLEN);

    while(scanf("%s", str) != EOF)
    {
       clear();
       if(!strcmp(str, "END"))
            return 0;

        int slen = strlen(str);
        for(int i = 0; i < slen; i++)
        {
            if(str[i] != '_')
            {
                item[str[i] - 'A'].freq++;
                item[str[i] - 'A'].ch = str[i];
            }
            else
            {
                item[26].freq++;
                item[26].ch = '_';
            }
        }

        for(int i = 0; i < R; i++)
            if(item[i].freq != 0)
                pq.push(item[i]);

        while(pq.size() != 1)
        {
            Item *item1 = new Item(' ', 0, NULL, NULL);
            Item *item2 = new Item(' ', 0, NULL, NULL);
            Item *parent = new Item(' ', 0, NULL, NULL);

            *item1 = pq.top();
            pq.pop();
            *item2 = pq.top();
            pq.pop();

            parent->ch = ' ';
            parent->freq = item1->freq + item2->freq;
            parent->left = item1;
            parent->right = item2;

            pq.push(*parent);
        }

        build_codetl(pq.top());

        int count = 0;
        for(int i = 0; i < R; i++)
        {
            count += ch[i].size() * item[i].freq;
        }
        printf("%d %d %.1f\n", slen*8, count, (slen*8.0) / count );
    }

    return 0;
}

这里的主要步骤是:1.统计字符及其出现的次数放到一个Item的对象中;2.为什么放到这样的对象中呢,因为是方便第二步的入队列,这里使用了一个优先级的队列,他们的优先级就是出现的频率,出现的频率越高,越是晚出队列;3,建立一个trie树,依次从队列中取出两个频率最低的元素,将其频率相加后再入队列,这样直到队列只剩下一个元素,这个元素就是trie树的根了;4,然后就是遍历trie树了,遍历的路径就是对应的huffman编码,分别给以存储就好了。这里用到两个函数,是因为假若输入的只有相同的元素的话,只有一个根节点,这样得不到正确的结果,因此对这种情况另外处理。


代码写得太罗嗦了。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值