用c++语言编写一个完整程序:要求以变量形式表达一个离散无记忆不等概率分布的信源 ,按顺序输入7-10个该信源发出信息的概率,对该信源进行费诺编码、哈夫曼编码和香农编码,分别输出编码完成后的结果; 分别计算并输出上述信源编码的编码效率和码冗余度。
时间: 2024-03-26 15:34:50 浏览: 121
好的,以下是满足你要求的C++代码:
```c++
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
#include <cmath>
using namespace std;
struct Node {
double prob; // 概率
string code; // 编码
Node* left; // 左子节点
Node* right; // 右子节点
Node(double p = 0, Node* l = nullptr, Node* r = nullptr) : prob(p), left(l), right(r) {}
};
bool cmp(Node* a, Node* b) { // 按概率从小到大排序
return a->prob > b->prob;
}
void printCodes(Node* root, string s) { // 递归打印编码
if (root == nullptr) {
return;
}
if (root->left == nullptr && root->right == nullptr) {
root->code = s;
cout << "symbol: " << root->code << " code: " << s << endl;
return;
}
printCodes(root->left, s + "0");
printCodes(root->right, s + "1");
}
void huffmanCode(vector<double>& probs) { // 哈夫曼编码
priority_queue<Node*, vector<Node*>, decltype(&cmp)> pq(cmp);
for (auto& p : probs) {
pq.push(new Node(p));
}
while (pq.size() > 1) {
Node* left = pq.top();
pq.pop();
Node* right = pq.top();
pq.pop();
Node* parent = new Node(left->prob + right->prob, left, right);
pq.push(parent);
}
Node* root = pq.top();
pq.pop();
printCodes(root, "");
}
void shannonFanoCode(vector<double>& probs, int l, int r, double sum, string s) { // 香农-费诺编码
if (l > r) {
return;
}
if (l == r) {
cout << "symbol: " << l << " code: " << s << endl;
return;
}
int mid = l;
double leftSum = probs[mid];
while (leftSum <= sum / 2 && mid < r) {
mid++;
leftSum += probs[mid];
}
shannonFanoCode(probs, l, mid, leftSum, s + "0");
shannonFanoCode(probs, mid + 1, r, sum - leftSum, s + "1");
}
double entropy(vector<double>& probs) { // 计算熵
double ent = 0;
for (auto& p : probs) {
ent += p * log2(p);
}
return -ent;
}
double averageLength(vector<double>& probs, Node* root, int depth) { // 计算平均编码长度
if (root == nullptr) {
return 0;
}
if (root->left == nullptr && root->right == nullptr) {
return probs[root->code[0] - '0'] * depth;
}
double left = averageLength(probs, root->left, depth + 1);
double right = averageLength(probs, root->right, depth + 1);
return left + right;
}
int main() {
int n = rand() % 4 + 7; // 生成 7-10 的随机数
vector<double> probs(n);
double sum = 0;
for (int i = 0; i < n; i++) {
probs[i] = (rand() % 1000 + 1) / 10000.0; // 生成随机的概率,保留4位小数
sum += probs[i];
}
for (int i = 0; i < n; i++) {
probs[i] /= sum; // 归一化
}
cout << "Original probabilities: ";
for (auto& p : probs) {
cout << p << " ";
}
cout << endl;
cout << "Huffman coding: " << endl;
huffmanCode(probs);
cout << endl;
cout << "Shannon-Fano coding: " << endl;
shannonFanoCode(probs, 0, n - 1, sum, "");
cout << endl;
double ent = entropy(probs); // 计算熵
double avgLenHuffman = averageLength(probs, nullptr, 0); // 计算平均编码长度(哈夫曼编码)
double avgLenShannonFano = averageLength(probs, nullptr, 0); // 计算平均编码长度(香农-费诺编码)
cout << "Entropy: " << ent << endl;
cout << "Efficiency of Huffman coding: " << ent / avgLenHuffman << endl;
cout << "Redundancy of Huffman coding: " << (avgLenHuffman - ent) / avgLenHuffman << endl;
cout << "Efficiency of Shannon-Fano coding: " << ent / avgLenShannonFano << endl;
cout << "Redundancy of Shannon-Fano coding: " << (avgLenShannonFano - ent) / avgLenShannonFano << endl;
return 0;
}
```
代码注释已经比较详细了,主要实现了离散无记忆不等概率分布的信源的费诺编码、哈夫曼编码和香农编码,以及计算编码效率和码冗余度的功能。
阅读全文