poj1521 huffman

第一次自己写huffman编码,我把建树和编码的全过程都写了一遍,其实可以不用编码,直接根据树的深度来计算即可,但是这题数据量不算大拿来练手吧。

不过用G++提交N次wrong answer.改用c++就过了,看来的花点时间看看她们的区别.

#include <string.h>
#include <iostream>
#include <stdio.h>
#include <string>
#include <stack>

using namespace std;
const int inf = 0x3f3f3f3f;

struct node{
    int freq;
    int data;
    int left, right;
};
node N[100];
char code[100][1000];
//stack<char> s;
//不支持迭代器
char s[1000];
int p ;

int select(int m, int *vis)
{
    int Min = inf;
    int pos = -1;
    for(int i = 0; i < m; i ++){
        if(N[i].freq < Min && vis[i] == 0){
            Min = N[i].freq;
            pos = i;
        }
    }
    vis[pos] = 1;
    return pos;
}

void huffman(int& n)
{
    int m = n;
    int vis[100];
    memset(vis, 0, sizeof(vis));
    for(int i = 0; i < m-1; i ++){
        int pos1 = select(n, vis);
        int pos2 = select(n, vis);
        // 选取最小的两个数字
        // cout << pos1 << " " << pos2 << endl;
        N[n].data = -1;   // 可以对数据进行其他处理
        // cout << N[pos1].freq << " " << N[pos2].freq << endl;
        N[n].freq = N[pos1].freq + N[pos2].freq;
        N[n].left = pos1;
        N[n].right = pos2;
        // 内部节点
        n ++;
       // cout << "n " << n << endl;
    }
}

void Travese(int n)
{
    // 用数组实现的二叉树的遍历
    // 小心空指针的代替,对于赋值为-1要注意数组越界
    if(n >= 0 && (N[n].data != inf)){
        //cout << N[n].freq << endl;
        cout << n << endl;
        Travese(N[n].left);
        Travese(N[n].right);
    }
}

void huffmancode(int n)
{
    if(n >= 0 && (N[n].data != inf)){
        if(N[n].left == -1 && N[n].right == -1){
           // cout << "n " << n << endl;
            for(int i = 0; i < p; i ++)
                code[n][i] = s[i];
           // cout << s << endl;
        }
        else{
            s[p++] = '0';
            huffmancode(N[n].left);
            p --;
            s[p++] = '1';
            huffmancode(N[n].right);
            p --;
        }
    }
}

int main()
{
    string data;
    int num[30];
    while(cin >> data){
        if(data == "END") break;
        memset(num, 0, sizeof(num));
        for(int i = 0; i < data.size(); i ++){
            if(data[i] == '_') num[0] ++;
            else{
                num[data[i]-'A'+1] ++;
            }
        }   
        for(int i = 0; i < 100; i ++){
            N[i].data = inf;
        }
        int n = 0;
        for(int i = 0; i < 30; i ++){
            if(num[i] > 0) {
                N[n].data = i;
                N[n].freq = num[i];
                N[n].left = -1;
                N[n].right = -1;
                n ++;
            }
        }
        int tag = n;
        //for(int i = 0; i < 30; i ++)
        //    cout << N[i].data << " " << N[i].freq << endl;

        huffman(n);   //  传递叶子节点和叶子节点数
        //cout << n << endl;
        //for(int i = 0; i < 60; i ++){
        //    cout << N[i].data << " " << N[i].freq << endl;
        //    cout << "x" << N[i].left << " " << N[i].right << endl;
        //}
        //Travese(n-1);
        p = 0;
        for(int i = 0; i < 100; i ++)
            memset(code[i], 0, sizeof(code[i]));
        huffmancode(n-1);
        int ans = 0;
        for(int i = 0; i < tag; i ++){
            // cout << code[i] << endl;
            ans += strlen(code[i])*N[i].freq;
            // 还要乘以权重
        }
        if(tag == 1)
            printf("%d %d %.1lf\n", 8*data.size(), data.size(), 8.0*data.size()/data.size());
        else
            printf("%d %d %.1lf\n", 8*data.size(), ans, 8.0*data.size()/ans);
    }
    return 0;
}


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值