【哈夫曼树】用优先队列简化哈夫曼树的构建(严书版数组父亲孩子法)

【哈夫曼树】用优先队列优化哈夫曼树的构建(严书版数组父亲孩子法)

严书代码思路:

哈夫曼树n个叶子节点的话必然是2n-1。
(1)用H数组的前n位(1~n)存这n个节点(权重, 父亲下标,左孩子下标,右孩子下标);
(2)从i=n+1的位置开始,每次从前面选两个权重最小的,把它们的权重和放到i位置,并修改挑出来的两个结点的父亲下标为i,i结点的左孩子下标和右孩子下标为两个结点的下标;
(3)重复(2),至i加到2n-1为止。
这个算法要是每次都用O(n)的线性遍历去找两个最小的话,复杂度是O(n²)的,这个过程可以用小顶堆优化,复杂度降为O(nlogn)

代码

#include <bits/stdc++.h>

using namespace std;
const int MAX_N = 1000, MAX_M = 2005;
struct node {
    int w;
    int parent, lchild, rchild;
};
typedef pair<int, int> P;//(权重, 下标)

int n,m;
int W[MAX_N];
node H[MAX_M];//父亲孩子法

//原理:用H数组前n位存叶子节点,之后的n-1位存它们的父节点
void mkHuff(){
    priority_queue<P, vector<P>, greater<P> > que;//按权重做小顶堆, 不过主要目的是在pop时得到在H数组中的下标

    for(int i = 0;i < n;i++){
        P no = {W[i],i};
        que.push(no);
        H[i] = {W[i], -1, -1, -1};//初始化三个指针都为-1
    }

    for(int i = n;i < m;i++){
        //取出两个最小的下标
        int pos1 = que.top().second;que.pop();
        int pos2 = que.top().second;que.pop();
        node newno = {H[pos1].w + H[pos2].w, -1, pos1, pos2};
        H[pos1].parent = i;
        H[pos2].parent = i;
        H[i] = newno;
        que.push({H[pos1].w + H[pos2].w, i});
    }
}


int main(){
    cin>>n;
    m = 2*n-1;

    //输入0到n-1这n个数的权重
    for(int i = 0;i < n;i++){
        cin>>W[i];
    }
    mkHuff();
    for(int i = 0;i < m;i++){
        cout<<H[i].w<<' '<<H[i].parent<<' '<<H[i].lchild<<' '<<H[i].rchild<<endl;
    }
    return 0;
}

/*
 5
 3 5 1 4 2
 */

输出:
输出

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值