算法-哈夫曼编码(贪心、c++、优先队列)

问题描述:

使用贪心算法求解Huffman编码问题,具体来说就是,根据每个字符的出现频率,使用最小堆构造最小优先队列,构造出字符的最优二进制表示,即前缀码。

【输入形式】在屏幕上输入字符个数和每个字符的频率。

【输出形式】每个字符的Huffman编码。字符从a开始,依次为b, c, ...

样例输入:

6
45 13 12 16 9 5

【样例输出】

a 0
b 101
c 100
d 111
e 1101
f 1100

【样例说明】

 输入:字符个数为6,a至f每个字符的频率分别为:45, 13, 12, 16, 9, 5。

 输出:a至f每个字符对应的Huffman编码。

说明:为了保证每个字符对应的Huffman编码的唯一性,对于所有测试样例,得到的Huffman编码树中,对于任何一个除叶结点以外的结点,其左儿子结点的频率小于其右儿子结点的频率(两者不会相等)。

c++代码

#include <iostream>
#include <queue>
#include <vector>
#include <map>
using namespace std;

struct node {
    char ch;
    int w;
    int flag;
    string s;
    node *left;
    node *right;
    node(char c, int weight, int f) : ch(c), w(weight), flag(f), s(""),left(nullptr), right(nullptr) {}
    bool operator>(const node &b) const {
        return this->w > b.w;
    }
};

// 自定义比较器,用于优先队列
struct CompareNode {
    bool operator()(node* const& n1, node* const& n2) {
        return n1->w > n2->w;
    }
};

// 自定义优先队列类型
priority_queue<node*, vector<node*>, CompareNode> q;

node *root; // 定义根节点

void hafuman() {
    while (q.size() > 1) {
        node *node1 = q.top();
        q.pop();
        node *node2 = q.top();
        q.pop();
        node *node3 = new node('\0', node1->w + node2->w, 0); // \0 作为非叶子节点的占位符
        node3->left = node1;
        node3->right = node2;
        q.push(node3);
    }

    root = q.top();
}

void printt(node *node,string ss, map<char, string> &codes) {
    if (node == nullptr) return;
    node->s=ss;
    if (node->flag == 1) {
        codes[node->ch]=node->s;
        
    }
    printt(node->left,ss+"0",codes);
    printt(node->right,ss+"1",codes);
}

int main() {
    int n;
    //cout << "输入字符个数: ";
    cin >> n;
    int f[11];
    //cout << "输入频率: ";
    for (int i = 0; i < n; i++) {
        cin >> f[i];
        char p = char(i + 97); // ASCII 'a' 的值是 97
        q.push(new node(p, f[i], 1));
    }
    hafuman();
    //cout << "前序遍历(根左右): ";
    map<char, string> codes;

    printt(root,"",codes);
    
    for (auto &pair : codes) {
        cout << pair.first << " " << pair.second << endl;
    }
    return 0;
}

结果

有很多可以优化的地方,这边只是一个简单的例子

  • 14
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是C++实现哈夫曼编码贪心算法的示例代码: ```c++ #include <iostream> #include <queue> #include <vector> #include <string> #include <unordered_map> using namespace std; // 定义哈夫曼树节点 struct HuffmanNode { char ch; // 字符 int freq; // 频率 HuffmanNode* left; // 左子节点 HuffmanNode* right; // 右子节点 HuffmanNode(char c, int f) : ch(c), freq(f), left(nullptr), right(nullptr) {} }; // 定义比较函数,用于优先队列 struct cmp { bool operator()(HuffmanNode* a, HuffmanNode* b) { return a->freq > b->freq; } }; // 构建哈夫曼树 HuffmanNode* buildHuffmanTree(unordered_map<char, int>& freqMap) { priority_queue<HuffmanNode*, vector<HuffmanNode*>, cmp> pq; for (auto& p : freqMap) { pq.push(new HuffmanNode(p.first, p.second)); } while (pq.size() > 1) { HuffmanNode* left = pq.top(); pq.pop(); HuffmanNode* right = pq.top(); pq.pop(); HuffmanNode* parent = new HuffmanNode('$', left->freq + right->freq); parent->left = left; parent->right = right; pq.push(parent); } return pq.top(); } // 递归遍历哈夫曼树,生成编码表 void generateHuffmanCode(HuffmanNode* root, string code, unordered_map<char, string>& codeMap) { if (!root) { return; } if (root->ch != '$') { codeMap[root->ch] = code; } generateHuffmanCode(root->left, code + "0", codeMap); generateHuffmanCode(root->right, code + "1", codeMap); } // 哈夫曼编码 string huffmanEncode(string s) { unordered_map<char, int> freqMap; for (char c : s) { freqMap[c]++; } HuffmanNode* root = buildHuffmanTree(freqMap); unordered_map<char, string> codeMap; generateHuffmanCode(root, "", codeMap); string res = ""; for (char c : s) { res += codeMap[c]; } return res; } // 哈夫曼解码 string huffmanDecode(string s, HuffmanNode* root) { string res = ""; HuffmanNode* cur = root; for (char c : s) { if (c == '0') { cur = cur->left; } else { cur = cur->right; } if (cur->ch != '$') { res += cur->ch; cur = root; } } return res; } // 测试代码 int main() { string s = "abacabad"; string encoded = huffmanEncode(s); cout << "Encoded string: " << encoded << endl; HuffmanNode* root = buildHuffmanTree({{'a', 2}, {'b', 2}, {'c', 1}, {'d', 1}}); string decoded = huffmanDecode(encoded, root); cout << "Decoded string: " << decoded << endl; return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值