poj1521

霍夫曼编码,建树

#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;

#define MAX_LENGTH 1005
#define MAX_ASCII 205
#define MAX_CHAR_CNT 300

struct Elem
{
    int pos;
    int cnt;
    Elem()
    {}
    Elem(int pp, int cc): pos(pp), cnt(cc)
    {}
};

struct Node
{
    int left_child;
    int right_child;
    int count;
}node[MAX_CHAR_CNT];

bool vis[MAX_CHAR_CNT];
char text[MAX_LENGTH];
int occurence_count[MAX_ASCII];
int node_cnt;
int original_length;
int ans;
int char_cnt;

bool operator < (const Elem &a, const Elem &b)
{
    return a.cnt > b.cnt;
}

void add_char(char ch)
{
    int asc = (int)ch;
    occurence_count[asc]++;
}

void add_node(int cnt)
{
    node[node_cnt].count = cnt;
    node[node_cnt].left_child = -1;
    node[node_cnt].right_child = -1;
    node_cnt++;
}

void count_char()
{
    memset(occurence_count, 0, sizeof(occurence_count));
    for (int i = 0; text[i]; i++)
    {
        add_char(text[i]);
    }
    node_cnt = 0;
    for (int i = (int)'A'; i <= (int)'Z'; i++)
    {
        if (occurence_count[i])
        {
            add_node(occurence_count[i]);
        }
    }
    if (occurence_count[(int)'_'])
        add_node(occurence_count[(int)'_']);
    original_length = strlen(text) * 8;
    char_cnt = node_cnt;
}

void build_tree()
{
    priority_queue<Elem> pq;
    memset(vis, 0, sizeof(vis));
    for (int i = 0; i < node_cnt; i++)
        pq.push(Elem(i, node[i].count));
    while (pq.size() > 1)
    {
        Elem a = pq.top();
        pq.pop();
        Elem b = pq.top();
        pq.pop();
        node[node_cnt].left_child = a.pos;
        node[node_cnt].right_child = b.pos;
        node[node_cnt].count = a.cnt + b.cnt;
        pq.push(Elem(node_cnt, a.cnt + b.cnt));
        node_cnt++;
        vis[a.pos] = true;
        vis[b.pos] = true;
    }
}

void dfs(int id, int depth)
{
    if (node[id].left_child == -1 && node[id].right_child == -1)
    {
        ans += node[id].count * depth;
        return;
    }
    if (node[id].left_child != -1)
        dfs(node[id].left_child, depth + 1);
    if (node[id].right_child != -1)
        dfs(node[id].right_child, depth + 1);
}

int main()
{
    while (scanf("%s", text), strcmp(text, "END"))
    {
        count_char();
        if (char_cnt == 1)
        {
            printf("%d %d 8.0
", original_length, original_length / 8);
            continue;
        }
        build_tree();
        ans = 0;
        dfs(node_cnt - 1, 0);
        printf("%d %d %.1f
", original_length, ans, original_length * 1.0 / ans);
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/rainydays/p/3273574.html