C++,已知一组包含至少8个字符的数组及各字符的出现概率(随机产生)。求该字符串数组的哈夫曼编码及平均码长。
时间: 2024-10-20 14:12:02 浏览: 40
在C++中,计算一个字符串数组的哈夫曼编码和平均码长通常需要两步:
1. **构造哈夫曼树**:
首先,你需要创建一个哈夫曼树。这涉及到将输入的概率分布转换成一个二叉树的过程,其中频率较高的字符位于较低层,而频率较低的字符位于较高层。你可以通过贪心算法(例如优先队列和合并节点)来进行构建。
```cpp
#include <queue>
#include <vector>
struct Node {
char ch;
int freq;
Node* left = nullptr;
Node* right = nullptr;
};
Node* constructHuffmanTree(const std::vector<int>& freqs) {
std::priority_queue<std::pair<int, Node*>, std::vector<std::pair<int, Node*>>, std::greater<> > pq;
for (auto& f : freqs)
pq.push({f, new Node {'.', f}});
while (pq.size() > 1) {
auto l = pq.top(); pq.pop();
auto r = pq.top(); pq.pop();
pq.push({l.first + r.first, new Node {'.', l.first + r.first, l.second, r.second}});
}
return pq.top().second;
}
```
2. **生成哈夫曼编码**:
创建完哈夫曼树后,遍历树并从根开始,对于每个左孩子记录0,右孩子记录1,直到到达叶子节点,得到的就是字符对应的二进制码。
```cpp
std::unordered_map<char, std::string> huffmanCode(Node* root) {
std::unordered_map<char, std::string> codeMap;
traverse(root, "", codeMap);
return codeMap;
}
void traverse(Node* node, std::string prefix, std::unordered_map<char, std::string>& codeMap) {
if (!node->left && !node->right) {
codeMap[node->ch] = prefix;
} else {
traverse(node->left, prefix + "0", codeMap);
traverse(node->right, prefix + "1", codeMap);
}
}
```
3. **计算平均码长**:
最后,计算所有字符的平均码长,公式是总码长除以字符数。
```cpp
double averageCodeLength(const std::unordered_map<char, std::string>& codeMap, const std::vector<int>& freqs) {
double totalLength = 0;
for (const auto& pair : codeMap) {
totalLength += pair.second.length() * freqs[pair.first];
}
return totalLength / freqs.size();
}
```
为了完成整个过程,首先你需要根据给定的概率生成一个字符数组,然后按照上述步骤操作。注意,这个描述假设了哈夫曼树仅用于表示单个字符及其频率,如果字符串中有多于一个字符的情况,你需要为每个字符分别进行编码。
阅读全文