首页 > 其他分享 >【模板】哈夫曼树

【模板】哈夫曼树

时间:2023-09-17 10:13:19浏览次数:30  
标签:node code return 哈夫曼 int ext var 模板

posted on 2021-08-02 20:03:57 | under 学术 | source

网上对哈夫曼树的讲解太少了

清一色指针

整个 OIer 能看的吧

虽然还是很恶心

下面是哈夫曼树的模板,解决的是经典问题:压缩字符串

#include <queue>
#include <string>
#include <iostream>
using namespace std;
template<int N,class var,class ext,int extlimit> struct Huffman{
    struct node{
        var w;ext e;
        int i,l,r;
        node(var w=0,ext e=0,int i=0,int l=0,int r=0):
            w(w),e(e),i(i),l(l),r(r){}
        bool operator>(const node &b)const{return w>b.w;}
    } a[N+10];
    int cnt,root;
    string code,ans[extlimit+10];
    Huffman():cnt(0),code(""){}
    string operator[](ext e){return ans[e];}
    node newnode(var w,ext e,int l=0,int r=0){return cnt++,a[cnt]=node(w,e,cnt,l,r);}
    void build(int n,var a[],ext e[]){
        priority_queue<node,vector<node>,greater<node> > q;
        for(int i=1;i<=n;i++) q.push(newnode(a[i],e[i]));
        while(q.size()>1){
            node t1=q.top();q.pop();
            node t2=q.top();q.pop();
            q.push(newnode(t1.w+t2.w,0,t1.i,t2.i));
        }
        return getcode(root=q.top().i);
    }
    void getcode(int now){
        if(!now) return ;
        if(!a[now].l&&!a[now].r) return (void)(ans[a[now].e]=code);
        code+='0',getcode(a[now].l),code.erase(--code.end());
        code+='1',getcode(a[now].r),code.erase(--code.end());
    }
};
Huffman<100010,int,char,128> huffman;
int n;
char a[100010];
int t[128];
int ipt[128],cnt;
char ipt2[128];
int main(){
    cin>>n>>(a+1);
    for(int i=1;i<=n;i++) t[a[i]*1u]++;
    for(int i=1;i<=127;i++){
        if(t[i]) ipt[++cnt]=t[i],ipt2[cnt]=i;
    }
    huffman.build(cnt,ipt,ipt2);
    for(int i=1;i<=n;i++) cout<<huffman[a[i]];
    return 0;
}

鉴于某些出题人(指 P2168 的)会让我们构造 \(k\) 叉哈夫曼树,那多挂一个代码吧:

#include <map>
#include <queue>
#include <string>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int inf=0x3f3f3f3f;
ostream& operator<<(ostream &fout,vector<int> &v){
    for(size_t i=0;i<v.size();i++) fout<<v[i]<<" ";
    return fout;
}
int K=2;
template<class var,class ext> struct Huffman{
    typedef vector<int> vec;
    struct node{
        var w;ext e;int i,h;vec ch;
        node(var w=0,ext e=0,int i=-1,int h=0,vec ch=vec()):
            w(w),e(e),i(i),h(h),ch(ch){}
        bool operator>(const node &b)const{
            if(w==b.w) return h>b.h;
            return w>b.w;
        }
    };
    vector<node> a;
    map<ext,string> ans;
    priority_queue<node,vector<node>,greater<node> > q;
    string operator[](ext e){return ans[e];}
    void insert(var w,ext e){q.push(newnode(w,e));}
    node newnode(var w,ext e,int h=0,vec ch=vec()){
        node tmp=node(w,e,a.size(),h,ch);
        return a.push_back(tmp),tmp;
   	}
    void build(){
        while((int)q.size()>=K){
            vec ch;var tot=0;
            int maxh=0;
            for(int i=0;i<K;i++){
                node tmp=q.top();q.pop();
                tot+=tmp.w;
                ch.push_back(tmp.i);
                maxh=max(maxh,tmp.h);
            }
            q.push(newnode(tot,0,maxh+1,ch));
        }
        return getcode(q.top().i,"");
    }
    void getcode(int now,string code){
        if(!a[now].ch.size()) return (void)(ans[a[now].e]=code);
        for(int i=0;i<K;i++) getcode(a[now].ch[i],code+(char)('0'+i));
    }
};
Huffman<LL,int> a;
int n;
LL w[100010];
LL ans,maxn;
int main(){
    ios::sync_with_stdio(0);
    cin>>n>>K;
    for(int i=1;i<=n;i++){
        cin>>w[i];
        a.insert(w[i],i);
    }
    if((n-1)%(K-1)!=0){
        for(int i=1;i<=K-1-(n-1)%(K-1);i++) a.insert(0,114514);
    }
    a.build();
    for(int i=1;i<=n;i++){
        ans+=a[i].size()*w[i];
        maxn=max(maxn,(LL)a[i].size());
    }
    cout<<ans<<endl<<maxn<<endl;
    return 0;
}

标签:node,code,return,哈夫曼,int,ext,var,模板
From: https://www.cnblogs.com/caijianhong/p/solution-huffman.html

相关文章

  • 模板方法模式
    在接口中定义算法步骤,子类实现算法步骤。拉起容器时既可以通过docker,也可以通过containerd。packagemainimport"fmt"typecontainerHandlestruct{ ccontainerHandler}typecontainerHandlerinterface{ create()error start()error}func(hcontainerHandl......
  • 【设计模式】模板方法模式Template Method:实现同一模板框架下的扩展
    (目录)模板方法模式的原理和代码实现都比较简单,也被广泛应用,但是因为使用继承机制,副作用往往盖过了主要作用,所以在使用时尤其要小心谨慎。原理模板方法模式原始定义是:在操作中定义算法的框架,将一些步骤推迟到子类中。模板方法让子类在不改变算法结构的情况下重新定义算法的某......
  • 博客页面模板
    简单的博客页面模板,并将背景颜色设置为白色:<!DOCTYPEhtml><html><head><style>body{background-color:white;margin:20px;font-family:Arial,sans-serif;}h1{color:#333;}p{color:#555;......
  • Vue-模板语法
    一、模板语法 插值语法最后都渲染成了字符串html:<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>Title</title><scriptsrc="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jque......
  • 深入剖析模板引擎:理解原理、应用场景和常见类型
    模板引擎是一种广泛应用于Web开发的工具,能够将动态数据与静态模板进行结合,生成最终的页面内容。本篇博客将详细介绍模板引擎的原理、常见应用场景以及多种类型的模板引擎。引言模板引擎是现代Web开发中不可或缺的一部分,它的作用是将静态的模板文件与动态的数据进行结合,生成最终呈......
  • C#使用NPOI读取模板生成EXCEL
     C#使用NPOI读取模板生成EXCELstringcurrentDirectory=System.AppDomain.CurrentDomain.BaseDirectory;//读取Excel模板文件FileStreamfs=newFileStream(currentDirectory+"BoxPackinglist.xlsx",FileMode.Open,FileA......
  • flask从入门到精通之钩子、异常、context、jinjia模板、过滤器
    一、请求全局钩子【hook】此处的全局钩子,其实就是类似django里面的中间件。也就是只要调用或者注册了,在http请求响应中是必然执行的。在客户端和服务器交互的过程中,有些准备工作或扫尾工作需要处理,比如:在项目运行开始时,建立数据库连接,或创建连接池;在客户端请求开始时,根据......
  • 【Vue】大悟!模板语法-插值语法&指令语法
    Vue系列持续更新模板语法Vue模板语法包括两大类插值语法插值语法也就是两个大括号,也叫Mustache功能:用于解析标签体内容,可以进行运算、三元表达式等,将最终解析出来的内容插入到标签中写法:{{xxx}},xxx是js表达式,可以直接读取到data中的所有区域插值表达式中只能放置单个表达式,不......
  • python利用openpyxl实现利用excel每行数据填入对应模板批量生成excel
    一、openpyxl常见操作可以参考:https://blog.csdn.net/JunChen681/article/details/1260532061、openpyxl把excel分成了三层Workbook是对工作簿的抽象(工作簿,一个excel文件包含多个sheet。)Worksheet是对表格的抽象(工作表,一个workbook有多个,表名识别,如“sheet......
  • 界面组件DevExpress WinForms v23.1亮点 - 全新升级HTML & CSS模板
    DevExpressWinForms拥有180+组件和UI库,能为WindowsForms平台创建具有影响力的业务解决方案。DevExpressWinForms能完美构建流畅、美观且易于使用的应用程序,无论是Office风格的界面,还是分析处理大批量的业务数据,它都能轻松胜任!DevExpressWinForm 控件已正式发布v23.1版本,此版......