SSL_1407【【树】哈夫曼树(一)】

这篇博客介绍了如何为8个出现频率不同的字母设计哈夫曼编码。通过构建哈夫曼树,按照左子树权值小于等于右子树权值的规则,给出了一种二进制编码方案。博客内容包括题目描述、输入输出格式、样例以及哈夫曼树在数据压缩中的应用。作者提到该算法在竞赛编程中较为罕见。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【树】哈夫曼树(一)

题目

假设用于通信的电文仅由8个字母组成,字母在电文中出现的频率分别为7、19、2、6、32、3、21、10。试为这8个字母设计哈夫曼编码。如果用二进制数表示这8个字母的编码方案.(请按照左子树根节点的权小于等于右子树根节点的权的次序构造

Input

第一行为字母的个数n;
第二行至第n+1行分别为各个字母在电文中出现的频率。

Output

按照中序遍历输出各个编码

Sample Input

8
7
19
2
6
32
3
21
10

Sample Output

19:00
21:01
2:10000
3:10001
6:1001
7:1010
10:1011
32:11

解析

啊不开SPJ就很烦的
烦又能怎么样呢,我又不会写SPJ
哈夫曼树,是一个最优叶子节点划分问题,常被用于压缩
不得不说这个算法是真的冷门,全洛谷只有一道荷马史诗是哈夫曼题

code:

#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
int n,x[10010]
根据引用中提到的,优先队列的时间复杂度为O(logn),其中n为队列中元素的个数。因此,使用priority_queue实哈夫曼的时间复杂度为O(nlogn),其中n为哈夫曼中叶子节点的个数。 实哈夫曼的步骤如下: 1. 统计每个字符在文本中出频率,并将其作为权值构建个森林,每个节点都是棵只包含个字符的。 2. 从森林中选出两棵根节点权值最小的,将它们合并成棵新,新的根节点权值为两棵的根节点权值之和。 3. 将新插入到森林中,并删除原来的两棵。 4. 重复步骤2和3,直到森林中只剩下,即为哈夫曼。 下面是使用priority_queue实哈夫曼的C++代码示例: ```c++ #include <iostream> #include <queue> using namespace std; struct TreeNode { char ch; int freq; TreeNode *left, *right; TreeNode(char c, int f) : ch(c), freq(f), left(NULL), right(NULL) {} }; struct cmp { bool operator() (TreeNode* a, TreeNode* b) { return a->freq > b->freq; } }; TreeNode* buildHuffmanTree(string s) { int n = s.size(); vector<int> freq(256, 0); for (int i = 0; i < n; i++) { freq[s[i]]++; } priority_queue<TreeNode*, vector<TreeNode*>, cmp> pq; for (int i = 0; i < 256; i++) { if (freq[i] > 0) { pq.push(new TreeNode(i, freq[i])); } } while (pq.size() > 1) { TreeNode* left = pq.top(); pq.pop(); TreeNode* right = pq.top(); pq.pop(); TreeNode* parent = new TreeNode('#', left->freq + right->freq); parent->left = left; parent->right = right; pq.push(parent); } return pq.top(); } int main() { string s = "hello world"; TreeNode* root = buildHuffmanTree(s); // do something with the Huffman tree return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值