赫夫曼树的创建(思路分析)

本文详细介绍了赫夫曼树的创建过程,包括从权值数组开始,通过排序、合并最小权值节点,逐步构建赫夫曼树。在构建过程中,重点讨论了如何使用Comparable接口对节点进行排序,以及如何在循环中不断更新和排序节点集合,直至形成完整的赫夫曼树。此外,还强调了循环结束条件及返回赫夫曼树头结点的重要性。
摘要由CSDN通过智能技术生成

赫夫曼树的创建(思路分析)

构成赫夫曼树的步骤:

  1. 从小到大进行排序,将有一个数据(每一个数据其实就是一个节点)看做是一颗最简单的二叉树

  2. 取出根节点权值最小的两颗二叉树(其实就是取出权值最小的两个结点)

  3. 用第2步中的两个二叉树组成为一颗新的二叉树, 该新二叉树的根节点的权值是前面两颗二叉树根节点的权值之和

  4. 再将这颗新的二叉树, 以根节点的权值大小再次排序, 不断重复1 - 2 - 3 - 4的步骤, 直到数列中, 所有的数据都被处理, 就得到一颗赫夫曼树

创建赫夫曼树的思路分析:

首先我们开始的时候是给我们一个数组, 数组中是哈夫曼树的叶子结点的权值, 我们通过这个数组来创建对应的哈夫曼树, 然后我们遍历这个数组, 将数组中的每一个元素构成一个哈夫曼树的结点, 然后我们将这一个个结点放入到我们的ArrayList集合中, 那么此时由于我们的数组中权值是无序的, 所以我们将数组中对应的权值封装到了对应的Node结点中之后, 这些Node结点也是无序的, 我们则需要这些Node结点按照权值进行排序,那么我们要如何对Node进行排序比较简洁

  • 我们此时的Node结点存储在一个ArrayList集合中, 因此我们可以通过Collections工具类中的sort()方法对ArrayList集合中的Node结点进行一个排序, 但是这个时候要注意: 我们的Node结点是一个对象, 而我们的引用数据类型本身是不能进行比较的, 也自然无法进行排序, 如果要我们的Node结点可以排序, 也就是可以比较, 那么我们就要让Node类去实现Comparable接口(java比较器接口), 如果不实现Comparable接口, 那么使用Collections工具类中的sort()方法对集合中的Node结点进行排序的时候会报一个类型转换异常, 就会显示Node结点元素无法转型为Comparable类型, 那么当我们的Node类去实现了Comparable接口之后我们这个时候其实还要在Node类中重写Comparable接口中的compareTo()比较方法,重写的这个compareTo()方法其实就是作为比较的依据, 假如结点的权被封装到了Node类的value属性中, 这个时候我们就要在compareTo()方法中去通过value值判断, 我们可以写为return this.value - o.value, this在前面形参在后面实现的compareTo()方法在调用排序方法的时候是从小到大排序, 也就是升序排序
    • 排好序之后我们就从集合中取出权值最小的结点
      • 注意: 由于后面的时候会向集合中添加一些新的树的头结点,所以其实可以说是集合中存储的都是一些二叉树(因为集合中存储的其实就是二叉树的根节点),所以其实就可以说是 存储的二叉树 —> 最初的时候集合中是一些单纯的结点, 但是第二次开始的时候,没排序之前集合中最后一个位置的Node结点肯定就是一个子树的头结点,然后后面的时候每次循环的时候排序前集合中最后一个位置的Node结点
    • 直接通过ArrayList接口中定义的通过索引的位置查找元素的方法, 传入一个0,那么找到的自然就是升序集合中的权值最小的结点
    • 然后我们再去吃权值第二小的结点(或者说是二叉树),通过ArrayList接口中定义的通过索引位置查找元素的方法, 传入一个1,那么找到的自然就是升序集合中的权值第二小的结点
      • 然后将我们取出的两个权值最小的二叉树合并为一个新的二叉树, 合并的时候其实就是先创建一个哈夫曼树结点, 这个新的哈夫曼树结点的权值是这两个最小权值的二叉树的权值之和, 然后使用这个新的结点指向我们的两个权值最小的二叉树的头结点即可
      • 然后将我们处理过的这两个权值最小的二叉树的根节点从我们的集合中删除掉, 将我们时候这两个权值最小的二叉树合并构建而成的新的二叉树的头结添加到我们的集合中去
        • 注意: 由于我们每次新添加的二叉树的头结点的值都是在集合的末尾位置(因为我们不知道要向什么具体的哪个位置添加,所以我们就干脆每次都将新的结点添加到集合的末尾即可), 而集合中末尾位置的结点的权值应该是最大权值结点, 我们的新添加的结点的权值可能并不是我们集合中权值最大的结点, 那么不是权值最大的结点我们如果将这个节点放到我们的集合中的末尾位置, 这个时候我们的集合的顺序就会有错误, 那么就会影响我们查找集合中的两个最小值的正确性, 所以我们就每次向集合中添加了新的结点之后都要对集合进行一个排序, 排序之后就能保证我们的集合中的结点的权值顺序是从小到大升序排序的, 那么我们就可以通过定位索引位置为0和索引位置为1的结点很快的就定位我们的集合中的最小元素和集合中的次小元素

对于上述的从找两个权值最小的结点的操作一直到最后的操作我们都可以放到一个循环中来解决, 循环退出的条件就是集合中如果只有一个元素的时候就退出, 因为每一次我们都是从集合中取出两个元素, 然后向集合中添加一个元素,那么其实每次都是减少集合中的一个元素, 在最后一次之前其实就是集合中剩余了两个元素, 然后我们就将这两个元素全部取出,取出之后集合中就一个元素都没有了, 然后最终我们又会想集合中添加一个元素, 然后添加了一个元素之后集合中就只剩下了一个元素, 此时我们就应该退出循环了 , 最终剩下的唯一的一个元素就是我们的哈夫曼树的头结点, 所以我们退出了循环之后就直接将我们的集合中的唯一的一个元素取出并返回即可

  • 在退出了询函之后一定要记的返回我们的最终的赫夫曼树的头结点, 也就是返回集合中的唯一剩余的一个元素
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值