哈夫曼树 HDU 1053 HDU 2527

#include<iostream> / * HDU 2527 裸的哈夫曼树 * /
#include<string>
#include<map>
using namespace std;
#define manx 100
#define inf 9999999;

map<char,int>mp;

struct node{
    int weight;
    int parent;
    int lch;
    int rch;
    string code;  ///  哈夫曼码值 
    string val;  ///  字符 
};

void init(node *hfnode,int n){ /// 初始化 
    for(int i=0;i<(n<<1)-1;i++){
        hfnode[i].weight=0;
        hfnode[i].parent=-1;
        hfnode[i].lch = hfnode[i].rch = -1;
        hfnode[i].code.clear();
        hfnode[i].val.clear();
    }
}

void make_tree(node *hfnode,int n){  /// 建哈夫曼树 
    int m1, m2, x1, x2;
    for(int i=1;i<n;i++){
        m1 = m2 = inf;  ///  记录最小和其次小的值 
        x1 = x2 = 0;  ///   记录最小和其次的值的位置 
        for(int j=1;j<n+i;j++){    ///   查询,找到最小和其次小的位置 
            if(hfnode[j].weight < m1 && hfnode[j].parent < 0){
                m2 = m1;
                x2 = x1;
                m1 = hfnode[j].weight;
                x1 = j;
            }
            else if(hfnode[j].weight < m2 && hfnode[j].parent <0 ){
                m2 = hfnode[j].weight;
                x2 = j;
            }
        }
        hfnode[x1].parent = n+i;  ///  然后父亲节点进行更新 
        hfnode[x2].parent = n+i;
        hfnode[n+i].weight = hfnode[x1].weight + hfnode[x2].weight;  ///  权值更新 
        hfnode[n+i].lch = x1;   ///  左右孩子进行记录 
        hfnode[n+i].rch = x2;
    }
}

void tree_code(node *hfnode, int m, int n ){  ///  采用递归的形式建立哈夫曼编码值 
    if( m<=n ) return ;
    if(hfnode[m].lch > 0) {
        hfnode[ hfnode[m].lch ].code = "0";
    }
    if(hfnode[m].rch > 0) {
        hfnode[ hfnode[m].rch ].code = "1";
    }
    tree_code( hfnode, hfnode[m].lch, n ); 
    tree_code( hfnode, hfnode[m].rch, n ); 
}

string e,hh;  /// hh 表示哈夫曼编码,它的长度也表示深度 
              /// e 表示目标 值 

void tree_dfs( node *hfnode,int m,int n,string s,int &flag ){  /// 深搜 
    if( hfnode[m].val == e ){  /// 查询 
        flag=1, hh=s;  
        return ;
    }
    if(flag || m <= n) return ;
    if(hfnode[m].lch > 0) {
        tree_dfs(hfnode,hfnode[m].lch, n, s+hfnode[ hfnode[m].lch ].code, flag);
    }
    if(hfnode[m].rch > 0) {
        tree_dfs(hfnode,hfnode[m].rch, n, s+hfnode[ hfnode[m].rch ].code, flag);
    }
}

int main(){
    node hfnode[manx*4];
    string str;
    int n1,t;
    cin>>t;
    while(t--){ 
        int ans1;
        cin>>ans1>>str;
        mp.clear();
        n1 = str.size();
        init(hfnode,manx);
        int n=0,ans=1;
        for(int i=0;i<n1;i++) mp[str[i]]++;
        for(int i=0;i<n1;i++){
            if(mp[str[i]]){
                hfnode[++n].weight = mp[str[i]];
                hfnode[n].val = str[i];
                mp[str[i]]=0; 
            }
        }
        int flag=0,sum=0,du=0;
        if(n==1) { 
            sum = hfnode[1].weight;
            if(sum<=ans1) printf("yes\n");
            else printf("no\n");
            continue;
        }
        make_tree(hfnode,n); 
        tree_code( hfnode,(n<<1)-1 ,n ); 
        string hfcode;
        
        for(int i=1;i<=n;i++){
            flag = 0;
            hfcode.clear();
            e.clear();
            hh.clear();
            e = hfnode[i].val;
            tree_dfs( hfnode, (n<<1)-1, n, hfcode, flag );
            sum += (hh.size())*(hfnode[i].weight);
        } 
        if(sum<=ans1) printf("yes\n");
        else printf("no\n");
    }
}


其实挺简单的,前几天自己写的课设就是哈夫曼树..

题意:要你求 8*str.size()   , sum(最优权值),   8*str.size()  /  (sum*1.0) 

代码:

/*

因为总计就是27个字符(状态),所以深搜是完全没有压力的 

*/ 

#include<iostream>
#include<string>
#include<map>
using namespace std;
#define manx 100
#define inf 9999999;

map<char,int>mp;

struct node{
    int weight;
    int parent;
    int lch;
    int rch;
    string code;  ///  哈夫曼码值 
    string val;  ///  字符 
};

void init(node *hfnode,int n){ /// 初始化 
    for(int i=0;i<(n<<1)-1;i++){
        hfnode[i].weight=0;
        hfnode[i].parent=-1;
        hfnode[i].lch = hfnode[i].rch = -1;
        hfnode[i].code.clear();
        hfnode[i].val.clear();
    }
}

void make_tree(node *hfnode,int n){  /// 建哈夫曼树 
    int m1, m2, x1, x2;
    for(int i=1;i<n;i++){
        m1 = m2 = inf;  ///  记录最小和其次小的值 
        x1 = x2 = 0;  ///   记录最小和其次的值的位置 
        for(int j=1;j<n+i;j++){    ///   查询,找到最小和其次小的位置 
            if(hfnode[j].weight < m1 && hfnode[j].parent < 0){
                m2 = m1;
                x2 = x1;
                m1 = hfnode[j].weight;
                x1 = j;
            }
            else if(hfnode[j].weight < m2 && hfnode[j].parent <0 ){
                m2 = hfnode[j].weight;
                x2 = j;
            }
        }
        hfnode[x1].parent = n+i;  ///  然后父亲节点进行更新 
        hfnode[x2].parent = n+i;
        hfnode[n+i].weight = hfnode[x1].weight + hfnode[x2].weight;  ///  权值更新 
        hfnode[n+i].lch = x1;   ///  左右孩子进行记录 
        hfnode[n+i].rch = x2;
    }
}

void tree_code(node *hfnode, int m, int n ){  ///  采用递归的形式建立哈夫曼编码值 
    if( m<=n ) return ;
    if(hfnode[m].lch > 0) {
        hfnode[ hfnode[m].lch ].code = "0";
    }
    if(hfnode[m].rch > 0) {
        hfnode[ hfnode[m].rch ].code = "1";
    }
    tree_code( hfnode, hfnode[m].lch, n );  
    tree_code( hfnode, hfnode[m].rch, n ); 
}

string e,hh; ///  hh表示哈夫曼编码,它的长度也算是深度
             ///  e 表示目标值 

void tree_dfs( node *hfnode,int m,int n,string s,int &flag ){  /// 深搜 
    if( hfnode[m].val == e ){  /// 当查询到时 
        flag=1, hh=s;
        return ;
    }
    if(flag || m <= n) return ; ///  两个成立的条件 
    if(hfnode[m].lch > 0) {
        tree_dfs(hfnode,hfnode[m].lch, n, s+hfnode[ hfnode[m].lch ].code, flag);
    }
    if(hfnode[m].rch > 0) {
        tree_dfs(hfnode,hfnode[m].rch, n, s+hfnode[ hfnode[m].rch ].code, flag);
    }
}

int main(){
    node hfnode[manx*4];
    string str;
    int n1; 
    while(getline(cin,str)){
        mp.clear();
        if(str=="END") break;
        n1 = str.size();
        init(hfnode,manx);
        int n=0,ans=1;
        for(int i=0;i<n1;i++) mp[str[i]]++;  /// map 统计单个字符出现的次数 
        for(int i=0;i<n1;i++){
            if(mp[str[i]]){
                hfnode[++n].weight = mp[str[i]];
                hfnode[n].val = str[i];
                mp[str[i]]=0; 
            }
        }
        if(n==1) {   要注意 
            cout<<8*str.size()<<" "<<hfnode[n].weight<<" ";
            printf("%.1lf\n",(8*str.size())/(hfnode[n].weight*1.0));
            continue;
        }
        make_tree(hfnode,n); 
        tree_code( hfnode,(n<<1)-1 ,n ); 
        string hfcode;
        int flag=0,sum=0,du=0;
        for(int i=1;i<=n;i++){
            flag = 0;
            hfcode.clear();
            e = hfnode[i].val;
            tree_dfs( hfnode, (n<<1)-1, n, hfcode, flag );
            sum += (hh.size())*(hfnode[i].weight);
        } 
        cout<<8*str.size()<<" "<<sum<<" ";
        printf("%.1lf\n",(8*str.size())/(sum*1.0));
    }
}

/*

THE_CAT_IN_THE_HAT
AAAAABCD

*/


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值