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\n", in.length()*8 ,ans , ( in.length()*8.0) / ans*1.0 );

    }

    return 0;

}

 

你可能感兴趣的:(HDU)