哈夫曼编码实验

实验目的

  1. 理解并熟练掌握哈夫曼编码原理
  2. 利用各种编程语言能够实现数字图像的哈夫曼编码算法

实验内容

  1. 编程实现数字图像的哈夫曼编码算法
  2. 利用所实现的上述算法,通过下面具体的实例,给出哈夫曼算法运行的结果,即显示出编码及码字长度(给出截图):

一幅40像素的黑白图像,有8个不同等级的亮度(灰度),分别用符号A—H表示,这些像素出现各种灰度的数量及概率如下图所示。

实验数据

实验要求

  1. 独立完成(但可以相互交流),禁止拷贝他人代码和实验结果,一经发现,将无实验成绩。
  2. 程序运行界面要显示出个人信息(班级、姓名、学号)。
  3. 实验过程要详细。

实验过程(算法实现)

include <iostream>
#include <queue>
#include <vector>

using namespace std;

struct Node{
    char c;
    int n;

    Node* left;
    Node* right;

    Node(char _c, int _n): c(_c), n(_n), left(nullptr), right(nullptr) {}
    Node(char _c, int _n, Node* l, Node* r): c(_c), n(_n) {
        left = l;
        right = r;
    }
};

struct cmp {
    bool operator()(Node*& a, Node*& b) const {
        return a->n > b->n;
    }
};

struct HuffmanTree{
    // 利用小根堆来自动排序
    priority_queue<Node*, vector<Node*>, cmp> heap;

    HuffmanTree() {
        cout << "请依次输入若干不同等级灰度的符号和出现频数,以频数0为结束:" << endl;
        char c;
        int n;
        while (cin >> c >> n && n) heap.push(new Node(c, n));
        while (heap.size() > 1) {
            // 每次取出频数最小的两个节点
            Node* t1 = heap.top();
            heap.pop();
            Node* t2 = heap.top();
            heap.pop();

            // 合并为一个节点,再插回堆中,起到排序的作用
            heap.push(new Node('0', t1->n + t2->n, t1, t2));
        }
        // 最后小根堆中就剩一个节点,就是哈夫曼树的根节点
    }

    // 遍历打印哈夫曼树
    void dfs(Node* u, string path) {
        if (!u->left && !u->right) cout << u->c << '\t' << u->n << '\t' << path << endl;
        if (u->left) dfs(u->left, path + '0');
        if (u->right) dfs(u->right, path + '1');
    }

    ~HuffmanTree() {
        while (heap.size()) {
            Node* t = heap.top();
            heap.pop();
            if (t->left) heap.push(t->left);
            if (t->right) heap.push(t->right);
            // cout << "删除节点:" << t->c << endl;
            delete t;
        }
    }
};

int main() {
    HuffmanTree ht;
    cout << "符号\t频数\t编码" << endl;
    ht.dfs(ht.heap.top(), "");
    return 0;
}

实验结果

结果截图

实验结果分析

频数或频率越高的符号的编码长度越短,越低的符号编码长度越长;且任何一个编码都不是其他任何编码的前缀,即不会产生歧义。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大西洋码头

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值