哈夫曼树与哈夫曼编码

全知识整理目录

数据结构整理的目录包括了许多的数据结构相关知识。


目录

概述

基本概念

构造哈夫曼树(过程)

构造哈夫曼树(代码)

哈夫曼编码


概述

什么是哈夫曼树呢?

哈夫曼树,又称为最优二叉树。给定n个权值作为n个叶子节点,构造一颗二叉树,若树的带权路径长度达到最小,则这棵树称为哈夫曼树。

简易理解:带权路径长度(WPL)最小的树就是哈夫曼树,WPL=所有叶子节点的权值*路径长度。

基本概念

路径长度:经过一个结点,路径长度就要+1,下图根节点到c的路径长度为3。

权值:每个结点都有一个权值(通常情况下,为了统一哈夫曼树,左边通常是小的权值结点)。

WPL(带权路径长度):WPL=7*1+5*2+3*(2+4)

构造哈夫曼树(过程)

构造哈夫曼树的基本步骤:

  1. 在给定权值中,选出最小的两个权值,对应两个结点组成一个新的二叉树,且新结点为两个左右孩子权值的和。
  2. 再选权值最小的结点,作为第一次组成的二叉树的根节点的兄弟结点。

这样就能排列出,一颗哈夫曼树。下面给出具体的步骤:

首先选出最小的两个结点(c,d)构成树。

再选出最小结点(b)和根节点构成二叉树。

再选出最小结点(a)和根节点构成二叉树。

得到最后的哈夫曼树。

构造哈夫曼树(代码)

结点构成

typedef struct{
    int weight;    //结点的权值
    int parent,left,right;    //父节点,左孩子,右孩子在数组中的位置下标。
}HTNode,*HuffmanTree;

哈夫曼树查找算法

//HT是哈夫曼树,end是HT数组存放结点的最后位置,s1.s2是传递数组种权重最小的那两个结点的位置
void Select(HuffmanTree HT, int end, int *s1, int *s2)
{
    int min1, min2;
    //遍历数组初始下标为 1
    int i = 1;
    //找到还没构建树的结点
    while(HT[i].parent != 0 && i <= end){
        i++;
    }
    min1 = HT[i].weight;
    *s1 = i;
   
    i++;
    while(HT[i].parent != 0 && i <= end){
        i++;
    }
    //对找到的两个结点比较大小,min2为大的,min1为小的
    if(HT[i].weight < min1){
        min2 = min1;
        *s2 = *s1;
        min1 = HT[i].weight;
        *s1 = i;
    }else{
        min2 = HT[i].weight;
        *s2 = i;
    }
    //两个结点和后续的所有未构建成树的结点做比较
    for(int j=i+1; j <= end; j++)
    {
        //如果有父结点,直接跳过,进行下一个
        if(HT[j].parent != 0){
            continue;
        }
        //如果比最小的还小,将min2=min1,min1赋值新的结点的下标
        if(HT[j].weight < min1){
            min2 = min1;
            min1 = HT[j].weight;
            *s2 = *s1;
            *s1 = j;
        }
        //如果介于两者之间,min2赋值为新的结点的位置下标
        else if(HT[j].weight >= min1 && HT[j].weight < min2){
            min2 = HT[j].weight;
            *s2 = j;
        }
    }
}

哈夫曼编码

哈夫曼编码就是在哈夫曼树的基础上建立的,这种编码的有点是,使用最少的字符,包含最多的信息。

对于树种的每一个子树,统一规定其左孩子标记为0,统一规定其右孩子标记为1。用到那个字符就从哈夫曼树的根节点开始,经过依次写出结点的标记,最终得到的就是哈夫曼编码。

所以,文本字符出现的次数越多就越接近树根,编码长度越短。

 如上图所示:字符a的哈夫曼编码是0,字符b的编码为10,字符c的编码为110,字符d的编码为111。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

ybbgrain

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

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

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

打赏作者

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

抵扣说明:

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

余额充值