zoukankan      html  css  js  c++  java
  • Hdu 1053 Entropy

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

    一道关于huffman树的题目。刚开始把各种字符看作一个结点,而这么一个结点同时也是一棵树。将这个字符出现的次数作为value。每次取出两个值最小的树,合并为一棵树,然后将这棵树再与其他结点放在一起排序。反复此步骤,直至只剩一棵树。那么,这棵树极为huffman树。

    最初想用优先队列排序,取出最小的两颗树,合并为一棵树后放回的策略。但可惜对c++内存方面理解不深透,怎么也做不出这棵树。

    最后只能用笨办法,建立一个数组,不断的排序取出最小的数。让后放回,再排序的策略。

    虽然过了,但感觉对huffman树的理解还是有很多不够,还需努力。

    /**
      Author : Emerald
      Date : 29.Jan 2015
      Aim : Hdu 1053
     */
    #include <iostream>
    #include <cstring>
    #include <cstdlib>
    #include <cstdio>
    #include <string>
    
    using namespace std;
    
    typedef struct Node{
        int value , depth; // value 表示出现的次数 , depth 表示此结点位于第几层,也就是深度
        struct Node *left, *right;
    
    }Node;
    
    // 用于 qsort() 函数
    int cmp( const void *a, const void *b ) {
        return (*(Node*)a).value - (*(Node*)b).value;
    }
    
    // 定义一个结点数组来保存一棵树.因为最多可能有27个字符,所以27×27的大小比较保险
    const int MAXN = 27*27;
    Node node[ MAXN ];
    
    int ans;
    void getEn( Node* t );
    
    // 建立huffuman树
    Node* buildTree( string in ) {
        int i, length = in.length();
    
        // 初始化,没有这一步会影响答案
        for( i=0; i<length*length && i<MAXN; i++ ) {
            node[i].value = node[i].depth = 0;
            node[i].left = node[i].right = NULL;
        }
    
        int hash[27] = { 0 };
        for( i=0; i<length; i++ ) {
            if( in[i] == '_' ) {
                hash[ 26 ] ++;
            } else {
                hash[ in[i]-'A' ] ++;
            }
        }
    
        int total = 0;
        for( i=0; i<27; i++ ) {
            if( hash[i] != 0 ) {
                node[ total ].value = hash[i];
                total ++;
            }
        }
    
        // 如果整个字符串只有一种字符,则直接返回节点
        if( total == 1 ) {
            ans = node[0].value; // = in.length
            return &node[0];
        }
    
        // 建立huffman树的关键步骤
        int pos = 0;
        while( pos != total-1 ) {
            qsort( node+pos, total-pos, sizeof( Node ), cmp );
            node[total].value = node[pos].value + node[pos+1].value;
            node[total].left = &node[pos];
            node[total].right = &node[pos+1];
            pos += 2;
            total ++;
        }
    
        // 将用于表示答案的变量初始化,这步决不能忘记
        ans = 0;
        return &node[pos];
    }
    
    
    // dfs 得出值
    void getEn( Node* t ) {
        if( t->left == NULL && t->right == NULL ) {
            ans = ans + t->depth * t->value;
            return ;
        }
    
        if( t->left != NULL ) {
            t->left->depth = t->depth + 1;
            getEn( t->left );
        }
    
        if( t->right != NULL ) {
            t->right->depth = t->depth + 1;
            getEn( t->right );
        }
    
    }
    
    int main()
    {
        string in;
        while( cin >> in ) {
            // 判断输入是否已经结束
            if( in.length()==3 ) {
                if( in[0]=='E' && in[1]=='N' && in[2]=='D' ) {
                    break;
                }
            }
    
            ans = 0 ;
            Node *t = buildTree( in );
            getEn( t );
            printf( "%d %d %.1lf
    ", in.length()*8 ,ans , ( in.length()*8.0) / ans*1.0 );
        }
        return 0;
    }
    
  • 相关阅读:
    MD5 初探。
    VFW程序分析
    IE版本简单兼容 JS闭包和JS对象解说。
    句柄和指针
    超时时间已到。在从池中获取连接之前超时时间已过。出现这种情况可能是因为所有池连接都已被使用并已达到最大池大小
    DataGrid模板列上的ImageButton 不能触发ItemCommand事件
    html转换成文本
    几种取数据库随机记录的方法
    打开.net时CPU占用率100%的问题个人处理办法
    强制输出wxl
  • 原文地址:https://www.cnblogs.com/Emerald/p/4259537.html
Copyright © 2011-2022 走看看