哈夫曼树(重点秒记 + 例题剖析)——>一篇带你学会(1)如何构造哈夫曼树,(2)如何生成哈夫曼编码集,(3)如何对数据进行哈夫曼编码(4)如何对数据进行哈夫曼阶码

哈夫曼树

必备知识

哈夫曼树 (Huffman Tree):

 1.一种用于数据压缩的二叉树,基于字符的频率构建。

 2. 是基于一个加权的完全二叉树,树中的每个节点代表一个字符(或数据元素)及其频率(或权重)。
 
 3. 核心思想是:将频率较低的元素放在树的较深位置,而将频率较高的元素放在较浅位置,这样可以实现最短的编码。

 4.哈夫曼树的构建算法主要采用贪心算法

 5. 每个字符的编码长度与其频率成反比,频率越高的字符,编码越短。

过程图解

(1)全部初始化为叶节点(只有根节点的树)

1

(2)选择字符频率最小的两个造新树

1

(3)删除原字符频率最小的两个节点,添加新节点(那两个节点的父节点)

1

(4)重复(2)(3)直到剩一个节点

1

例题详解


例 1 :哈夫曼树编码(易)


题目描述
哈夫曼树编码

问题描述
哈夫曼树编码
给定K个不同的字符和它们的频率,建立一棵哈夫曼树对字符进行编码,合并后的节点字符设为#。合并节点时频率小的在右边,频率相同时字符小的在右边,频率和字符都相同时,后生成的节点放右边。节点频率相同的时候优先选取节点字符值大的先进行结合。

要求按照后序遍历的顺序输出哈夫曼树中叶子节点的字符。
输入包含两部分,第一部分一个数字K表示有K个字符,第二部分有K行,每行两个数表示字符和它的频率。

样例输入
7
A 5
F 5
C 7
G 13
E 34
B 24
D 17
​
​
样例输出
E
D
G
B
F
A
C


实现思路

递归判断
AVL

由于我们针对的是 AVL 树,忘了见对应知识点–AVL

 1. 设置递归终止条件

      空节点:返回 true

 2. 递归判断当前节点左右子树是否平衡并得到左右子树的高度
      
 3. 计算当前节点的左右子树高度差的绝对值是否超过 1

实现代码
#include <iostream>
#include <chrono>
#include <queue>
#include <vector>
#include <unordered_map>
using namespace std;

// 哈夫曼树节点定义
struct HuffmanNode
{
   
     char data;
     int freq;
     HuffmanNode *left;
     HuffmanNode *right;
     HuffmanNode(char data, int freq) : data(data), freq(freq), left(nullptr), right(nullptr) {
   }
};

// 排序规则
struct _Compare
{
   
     bool operator()(HuffmanNode *a, HuffmanNode *b)
     {
   
          if (a->freq == b->freq)
               return a->data > b->data;
          else
               return a->freq > b->freq;
     }
};
// 哈夫曼树类
class HuffmanTree
{
   
     // 哈夫曼树根节点
    HuffmanNode *root;

    // 后序遍历输出内部方法实现
    void postOrder(HuffmanNode *root, vector<char> &result)
    {
   
        if (root == nullptr)
            return;
        postOrder(root->left, result);
        postOrder(root->right, result);
        if (root->data != '~')
            result.push_back(root->data);
    }

     // 内存清理内部方法实现
     void DeleteHuffmanTree(HuffmanNode *node)
    {
   
     
        if (node)
        {
   
            DeleteHuffmanTree(node->left);
            DeleteHuffmanTree(node->right);
            delete node;
        }
    }
    

public:
    HuffmanTree() : root(nullptr) {
   }
    ~HuffmanTree() {
    DeleteHuffmanTree(root); }

    //建树
    
参考资源链接:[2022大连理工考研810数据结构与计算机组成原理大纲详解](https://wenku.csdn.net/doc/287tr0vtj5?utm_source=wenku_answer2doc_content) 在准备大连理工大学考研的过程中,掌握如何在C++中实现哈夫曼及其算法分析是非常重要的。哈夫曼是一种特殊的二叉,用于数据压缩中的哈夫曼编码,具有最小的权路径长度。为了更好地理解这一概念及其应用,可以参考这本资料《2022大连理工考研810数据结构与计算机组成原理大纲详解》。它详细讲解了考研大纲要求的各个知识点,包括哈夫曼的构建方法和算法分析。 在C++中实现哈夫曼的基本步骤包括: 1. 定义节点类,包含权值、指向左右子的指针等属性。 2. 创建一个优先队列(最小堆)来存储所有节点,根据权值进行排序。 3. 不断地取出最小的两个节点,创建一个新的内部节点作为它们的父节点,权值为两者之和,然后将这个新节点加入优先队列中。 4. 重复步骤3,直到优先队列中只剩下一个节点,这最后一个节点即为哈夫曼的根节点。 算法的时间复杂度分析: - 首先,初始化优先队列,每个节点入队一次,时间复杂度为O(n)。 - 然后,重复n-1次合并操作,每次合并操作需要从优先队列中取出两个节点并插入一个新的节点,由于优先队列的插入和删除操作的时间复杂度为O(logn),因此总的复杂度为O(nlogn)。 - 综上,整个构建哈夫曼的过程的时间复杂度为O(nlogn)算法的空间复杂度分析: - 空间复杂度主要由节点数量决定,为O(n),因为最坏情况下,的节点数接近2n(除了叶子节点外,每个节点都有一个父节点)。 推荐的辅助资料《2022大连理工考研810数据结构与计算机组成原理大纲详解》能够提供对哈夫曼算法分析的深入讲解,并通过具体例题帮助理解如何将理论知识应用于实际问题的解决。建议考生在深入理解哈夫曼的实现原理后,继续深入学习计算机组成原理的相关知识,以及如何将数据结构应用于解决更广泛的问题。 参考资源链接:[2022大连理工考研810数据结构与计算机组成原理大纲详解](https://wenku.csdn.net/doc/287tr0vtj5?utm_source=wenku_answer2doc_content)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值