哈夫曼树和哈夫曼编码

哈夫曼树和哈夫曼编码 HUFFMAN

1. 哈夫曼树

  1. 引例:将百分制的考试成绩转换成五分制的成绩,且考虑学生成绩的分布的概率

    • 判定方式一
      • 代码逻辑
      • 二叉判定树
      • 查找效率
    • 判定方式二
      • 代码逻辑
      • 二叉判定树
      • 查找效率
    • 我们发现,第二种判定树的搜索效率更好
  2. 核心问题:如何根据结点不同的查找频率构造更有效的搜索树

  3. 哈夫曼树

    • 带权路径长度(WPL):设二叉树有 n 个叶子结点,每个叶子结点带有权值 w k w_k wk,从根结点到每个叶子结点的长度为 l k l_k lk,则每个叶子结点的带权路径长度之和就是: W P L = Σ k = 1 n w k l k WPL = Σ_{k=1}^{n}w_kl_k WPL=Σk=1nwklk
    • 最优二叉树 or 哈夫曼树:即 WPL 最小的二叉树
  4. 哈夫曼树的构造:即构造一棵二叉树,同时使得 WPL 值最小

    • 构造方式:每次把权值最小的两棵二叉树合并
    • 算法实现思路
      • 从当前“叶子结点列表”中取出两个最小的结点合并成一个二叉树,新的二叉树结点权值是这两个结点权值的和,并且将这个结点添加到“叶子结点列表”中去
      • 循环上述流程,直到“叶子结点列表”只有一个一个结点时,哈夫曼树构造终止
    • 代码实现逻辑:依据最小堆实现代码
      • 每次从最小堆取两个最小的结点进行合成
    • 算法分析:时间复杂度为 O(NlogN)
      HuffmanTree Huffman(MinHeap H)
      {
      	/* 假设 H->Size 个权值已经存在 H->Elements->Weight 里 */
      	/* 根据哈夫曼构建思路,一共只需要循环 n-1 次 */
      	/* 循环结束后,此时 H 中也只有一个结点了,就是根节点 */
      	HuffmanTree T;
      	BuildHeap(H); // 根据传入的 H(至少是一个完全二叉树),将 H->Elements[] 按照权值调整为最小堆
      
      	for (int i = 1; i < H->Size; i++)
      	{
      		T = (HuffmanTree)malloc(sizeof(HuffmanTreeNode));
      		T->Left = DeleteMin(H); // 从最小堆里边删除两个最小的结点,共同构建一个二叉树
      		T->Right = DeleteMin(H);
      		T->Weight = T->Left->Weight + T->Right->Weight; // 更新权值
      
      		Insert(H, T);
      	}
      
      	T = DeleteMin(H);
      	return T;
      }
      

    〖例〗 有五个叶子结点,它们的权值为{1,2,3,4,5},用此权值序列可以构造出形状不同的多个二叉树。

    • 构造一颗哈夫曼树

      此时 WPL = 12
    • 其他情形
  5. 哈夫曼树的特点

    • 没有度为 1 的结点
    • 哈夫曼树的任意非叶节点的左右子树交换后仍是哈夫曼树
    • n 个叶子结点的哈夫曼树共有 2n-1 个结点
      • 简证 n 0 = n 2 + 1 , n 1 = 0 , n 0 = n = > n a l l = n 1 + n 2 + n 3 = 2 n − 1 n_0=n_2+1,n_1=0,n_0=n=>n_all=n_1+n_2+n_3=2n-1 n0=n2+1,n1=0,n0=n=>nall=n1+n2+n3=2n1
    • 对同一组权值{w1 ,w2 , …… , wn},存在不同构的两棵哈夫曼树

2. 哈夫曼编码

  1. 引言:给定一段字符串,我们可以对字符进行编码,我们有“等长编码”和“不等长编码”两种实现方式,那么在知道每个字符的使用频率的情况下,怎么编码才能使得字符串空间花费最小,这就是我们要研究的问题。
  2. 根据上述的思考,我们很容易知道,这个编码问题和哈夫曼树的联系,路径长度就是每个字符编码的位数,每个字符的权值就是其出现的频率,二者相加求和就是对字符串编码所需要的空间大小。因此,为了实现最佳编码机制,我们需要构建一个哈夫曼二叉树去实现
  3. 二叉树编码
    • 左右分支取 0、1,且字符只存在于叶节点上
      • 等长二叉树编码
      • 不等长二叉树编码(通过哈夫曼树实现则代价最小)
        • 哈夫曼编码是通过哈夫曼树实现的编码机制,其 ①确保编码无二义性 ②总代价最小( c o s t = Σ 1 n 频率 × 路径长度 cost=Σ_1^n频率×路径长度 cost=Σ1n频率×路径长度
    • 举例:假设四个字符频率为 a:4,u:1,x:2,z:1

  4. 不等长编码的注意:要避免二义性!!!即任何字符的编码都不能是另一字符编码的前缀,否则无法解码。
  5. 哈夫曼编码举例
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值