算法实践11 哈夫曼编码

问题:

给定字符集\(C={x_1,x_2,\dots,x_n}\)和每个字符的频率\(f(x_i)\),求关于\(C\)的一个最优前缀码

解析

将所有的字符丢进一个堆中,按出现频率从小到大排序。按照哈夫曼算法,优先取出两个堆顶的元素,把它们出现的频率加在一起,再丢到堆里,直到只剩一个元素,就是最终得到的答案。

设计

while (q.size() > 1) {
    取出栈顶的两个元素进行合并编号,建立结点关系
    放回栈里
}

分析

for循环\(O(n)\),维护堆\(O(nlogn)\),算法时间复杂度\(O(nlogn)\)

源码

https://github.com/Sstee1XD/Algorithm_homework/tree/main/实验11 哈夫曼编码

#include <bits/stdc++.h>

using namespace std;

#define endl "\n"

const int inf = 0x3f3f3f3f;
const int N = 1e3 + 7;

int n;
int fa[N], ww[N];
vector<int> son[N];

struct Node {
    int id, w;
    bool operator < (const Node &a) const {
        return w > a.w;
    }
};

void solve() {
    scanf("%d", &n);
    priority_queue<Node> q;
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &ww[i]);
        q.push({i, ww[i]});
    }
    while (q.size() > 1) {
        Node l = q.top();
        q.pop();
        Node r = q.top();
        q.pop();
        int id = ++n, w = l.w + r.w;
        ww[id] = w;
        fa[l.id] = id, fa[r.id] = id;
        son[id].push_back(l.id);
        son[id].push_back(r.id);
        q.push({id, w});
    }
    fa[q.top().id] = -1;
    q.pop();
    for (int i = 1; i <= n; ++i) {
        printf("id:%d\tweight:%d\tparent:%d\t", i, ww[i], fa[i]);
        if (son[i].size() == 0) {
            printf("lson:-1\trson:-1\n");
        } else {
            printf("lson:%d\trson:%d\n", son[i][0], son[i][1]);
        }
    }
}

int main() {
    // scanf("%d", &t);
    int t = 1;
    while (t--) solve();
    return 0;
}
/*
8
5 5 10 10 10 15 20 25
*/
posted @ 2021-06-23 01:43  stff577  阅读(60)  评论(0)    收藏  举报