Huffman

先从简单的Huffman树讲起
我们选用优先队列构造小顶堆,每次从堆中提取最小元素
以一个例子作为引子:

搬水果

ps:priority_queue<int> q;直接得到的是大顶堆,每次输出的是队列中最大的元素
我们需要将其改为priority_queue<int,vector<int>,greater<int> > q;
才能改变堆为小顶堆

程序不难,反复输出即可

//注意取值范围
#include<iostream>
#include<queue>
#include<vector>
using namespace std;
priority_queue<long long,vector<long long>,greater<long long> > q;
long long data;//果子个数
int n;//果子种类数
int main(){
    while(cin>>n){
        for(int i=0;i<n;i++){
            cin>>data;
            q.push(data);
        }
        long long a,b,ans=0;
        while(q.size()>1){
            a=q.top();
            q.pop();
            b=q.top();
            q.pop();
            ans=ans+a+b;
            q.push(a+b);
        }
        cout<<ans<<endl;
    }
    return 0;
}

再看构建一棵huffman树
构建树就必然会带来左右孩子的问题,有左右孩子就会有指针存在。胡凡大神给出的解决方式是分配一个静态的结点数组,每次都分配新结点就从结点数组中取,这样可以保证每个结点的地址不同。
我开始没有采用这种做法,申请左右孩子新结点时,按照以下步骤来进行:

while(true){
	node a,b;
	father.rchild=a;
	father.lchild=b;
}

这里存在这让程序员最为头疼的问题,while中每次node都会指向while内部地址(ps:不知道我理解的对不对)导致每次的新结点都会指向同一个地址从而引发了无穷递归问题。
所以我们采用胡凡大神提供方法,设置静态数组
局部操作如下:

node* creat(){
    size++;
    return &nodes[size];
}

全部的huffmanCode:

#include<iostream>
#include<queue>
#include<vector>
#include<string>
using namespace std;
//使用静态分配树结点方式
//否则指针地址很难解决
const int maxn=1000;
struct node{
    double data;
    node *lchild,*rchild;
    bool operator > (const node b) const{
        return this->data > b.data;
    }
}nodes[maxn];
int size=-1;//借助size顺序分配结点
priority_queue<node*,vector<node*>,greater<node*> > q;
node* creat(){
    size++;
    return &nodes[size];
}
void preorder(node* r){//前序遍历huffman树
    if(r!=NULL){
        cout<<r->data<<endl;
        preorder(r->lchild);
        preorder(r->rchild);
    }
}
void huffmancode(node *r, string s){
    if(r!=NULL){
        string s1=s+"0",s2=s+"1";
        huffmancode(r->lchild,s1);
        huffmancode(r->rchild,s2);
        if(r->rchild==NULL&&r->lchild==NULL)
            cout<<s<<endl;
    }
}
int main(){
    int n;
    double d;
    node* tmp;
    cin>>n;
    for(int i=0;i<n;i++){
        tmp=creat();
        cin>>tmp->data;
        tmp->lchild=NULL;
        tmp->rchild=NULL;
        q.push(tmp);
    }
    while(q.size()>1){
        node *a,*b;
        node *res=creat();
        a=q.top();q.pop();
        b=q.top();q.pop();
        res->data=a->data+b->data;
        res->lchild=a;
        res->rchild=b;
        q.push(res);
    }
    tmp=q.top();q.pop();
    //preorder(tmp);
    huffmancode(tmp,"");
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值