zoukankan      html  css  js  c++  java
  • Haffman编码(haffman树)

    Haffman编码

    时间限制:1000 ms  |  内存限制:65535 KB
    难度:3
     
    描述

    哈弗曼编码大家一定很熟悉吧(不熟悉也没关系,自己查去。。。)。现在给你一串字符以及它们所对应的权值,让你构造哈弗曼树,从而确定每个字符的哈弗曼编码。当然,这里有一些小规定:

    1.规定哈弗曼树的左子树编码为0,右子树编码为1;

    2.若两个字符权值相同,则ASCII码值小的字符为左孩子,大的为右孩子;

    3.创建的新节点所代表的字符与它的左孩子的字符相同;

    4.所有字符为ASCII码表上32-96之间的字符(即“ ”到“`”之间的字符)。

     
    输入
    输入包含多组数据(不超过100组) 每组数据第一行一个整数n,表示字符个数。接下来n行,每行有一个字符ch和一个整数weight,表示字符ch所对应的权值,中间用空格隔开。 输入数据保证每组测试数据的字符不会重复。
    输出
    对于每组测试数据,按照输入顺序输出相应的字符以及它们的哈弗曼编码结果,具体格式见样例。
    样例输入
    3
    a 10
    b 5
    c 8
    4
    a 1
    b 1
    c 1
    d 1
    样例输出
    a:0
    b:10
    c:11
    a:00
    b:01
    c:10
    d:11
    题解:让求一颗哈夫曼树,哈夫曼树是先找到最小的两个建一个根节点,这个根节点的权值为两个小的权值和;
    加入这个新节点,重新找;用优先队列实现;其根节点即为元素在树中的位置;
    代码:
    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    using namespace std;
    const int INF=0x3f3f3f3f;
    #define mem(x,y) memset(x,y,sizeof(x))
    #define SI(x) scanf("%d",&x)
    #define PI(x) printf("%d",x)
    typedef long long LL;
    string ans[300];
    char c[310];
    struct Node{
        char c;
        int v;
        Node *l,*r;
        Node(){
            l=r=NULL;
        }
        Node(char ch,int vv,Node *ll=NULL,Node *rr=NULL){
            c=ch;v=vv;l=ll;r=rr;
        }
        bool operator < (const Node &b) const{
            if(v!=b.v)return v>b.v;
            else return c>b.c;
        }
    };
    Node e[300];
    void dfs(Node *now,string s){
        if(now->l==NULL&&now->r==NULL){
            ans[int(now->c)]=s;return;
        }
        if(now->l!=NULL)dfs(now->l,s+'0');
        if(now->r!=NULL)dfs(now->r,s+'1');
        return ;
    }
    int main(){
        int N,v;
        //char s[2];
        while(~SI(N)){
            if(N==0)continue;
            for(int i=0;i<300;i++)e[i].l=e[i].r=NULL;
            priority_queue<Node>Q;
            getchar();
            for(int i=0;i<N;i++){
                scanf("%c %d",&c[i],&v);getchar();//这里不这样输入就错了 
                //c[i]=s[0];
                Q.push(Node(c[i],v));
            }    
            int tp=0;
            while(Q.size()>1){
                e[tp++]=Q.top();
                Q.pop();
                e[tp++]=Q.top();
                Q.pop();
                Q.push(Node(e[tp-2].c,e[tp-2].v+e[tp-1].v,&e[tp-2],&e[tp-1]));
                //Node(e[tp-2].c这样插是为了当和等于下一个的v的时候排在前边;
                //为什么要再开一个数组e:为了保持队列里面元素的l,r对应关系; 
            }
            Node ss;
            ss=Q.top();
            //printf("%c %d
    ",ss.c,ss.v);
            dfs(&ss,"");
            //printf("****");
            for(int i=0;i<N;i++){
                //printf("%c:%s
    ",c[i],ans[int(c[i])].c_str());
                  cout<<c[i]<<":"<<ans[int(c[i])]<<endl;
            }
        }
        return 0;
    }

     数据结构课后又写了下:优先队列那点要用仿函数写;

    代码:

    #include "handsomecui.h"
    #include<queue>
    #include<vector>
    struct Node{
        int v;
        char c;
        Node *l, *r;
        Node(){
            l = NULL;
            r = NULL;
         }
        void init(int v, char c, Node *l = NULL, Node *r = NULL){
            this->v = v;
            this->c = c;
            this->l = l;
            this->r = r;
        }
    //    bool operator < (const Node *a) const{
    //        return v > a->v;//这里的排序有问题 
    //    }
    };
    struct cmp{
        bool operator() (const Node *a, const Node *b) const{
            if(a->v != b->v)
                return (a->v) > (b->v);
            else
                return a->c > b->c;
        }
    };
    priority_queue<Node*, vector<Node*>, cmp>Q;
    string ans[300];
    void dfs(Node *root, string s){
        if(root->l == NULL && root->r == NULL){
            ans[root->c] = s;
            return;
        }
        if(root->l != NULL){
            dfs(root->l, s + '0');
        }
        if(root->r != NULL){
            dfs(root->r, s + '1');
        }
    }
    char s[310];
    void print(char c){
        PI(c, ":");
        PI(ans[c] , "
    ");
    }
    int main(){
        int n;
        int v;
        while(~scanf("%d", &n)){ 
            if(n == 0)
                continue;
            getchar();
            while(!Q.empty())
                Q.pop();
            Node *a, *b, *c;
            for(int i = 0; i < n; i++){
                a = new Node();
                scanf("%c%d", &s[i], &v);
                getchar();
                a->init(v, s[i]);
                Q.push(a);
            }
            while(Q.size() > 1){
                a = Q.top();
                Q.pop();
                b = Q.top();
                Q.pop();
                c = new Node();
                c->init(a->v + b->v, a->c, a, b);
                Q.push(c);
            }
            dfs(Q.top(), "");
            for_each(s, s + n, print);
        }
        return 0;
    }
  • 相关阅读:
    CSS3学习-用CSS制作立体导航栏
    JS学习-事件响应小结-简单的计算器
    BOM学习-javascript计时器小结
    php 正则表达式
    zTree插件的应用
    css样式篇
    iso移动端input的bug解决(vue)
    html2canvas文字重叠(手机端)
    react中使用antd遇到的问题
    react开发初始配置和一些问题
  • 原文地址:https://www.cnblogs.com/handsomecui/p/5230597.html
Copyright © 2011-2022 走看看