算法系列之赫夫曼树的精解【构造流程及原理分析】

赫夫曼树又称为最优树、最优二叉树

赫夫曼树百度百科https://baike.baidu.com/item/%E5%93%88%E5%A4%AB%E6%9B%BC%E6%A0%91/2305769?fromtitle=%E8%B5%AB%E5%A4%AB%E6%9B%BC%E6%A0%91&fromid=7406794&fr=aladdin

📚赫夫曼树相关的名词

(1).路径

📑一个结点到另外一个结点的通路成为路径

(2).路径长度

📑通路中分支的数目称为路径长度,若规定根结点的层数为1,则从根结点到第L层结点的路径长度为L-1。

(3).结点的权

📑若将树中结点赋给一个有着某种含义的数值,则这个数值称为该结点的权

(4).结点的带权路径长度

📑从根结点到该结点之间的路径长度与该结点的权的乘积。

(5).树的带权路径长度

📑树的带权路径长度规定为所有叶子结点的带权路径长度之和,记为WPL。

赫夫曼树的特点

在构建哈弗曼树时,要使树的带权路径长度最小,只需要遵循一个原则,那就是:权重越大的结点离树根越近。在图 1中,因为结点 a 的权值最大,所以理应直接作为根结点的孩子结点。
在这里插入图片描述
📚赫夫曼树的构建流程分析

以该结点集合[5,29,7,8,14,23,3,11]为例

1.讲每个结点存放到集合当中
在这里插入图片描述
2.对该集合进行排序(按照权值大小)
在这里插入图片描述
3.从集合中取出两个结点,创建一个新的结点作为它们的父节点,父节点的权值等于两个子节点的之和。

在这里插入图片描述
4.讲父节点加入到集合当中,从集合中移除这两个子结点
在这里插入图片描述
5.周而复始的执行1~4步即可,直到list.size <= 1;此时集合中剩下最后一个结点,而这个结点就是哈夫曼树的根节点(100)

在这里插入图片描述
📚源代码

public class HuffmanTree {
	//测试
    public static void main(String[] args) {
        int[] arr = {13, 7, 8, 3, 29, 6, 1};
        HuffNode root = buildHuffmanTree(arr);
        preErgodic(root);
    }
	/**
	 *1.首先遍历数组,将权值依次封装到HuffNode对象中,并加入到List集合
	 *2.由于实现类Comparable接口,所以使用Collections.sort进行集合排序
	 *3.分别从集合中取出两个结点,然后创建一个新的父节点(父节点的权值即为两个子节点的权值之和,将left和right指针分别指向两个子节点。
	 *4.将父节点加入到list集合中
	 *5.循环1-4步,直到size == 1 ,也就是集合中只剩下哈夫曼树的根节点
	 */
    private static HuffNode buildHuffmanTree(int[] arr) {
        List<HuffNode> list = new ArrayList<>();
        for (int value : arr) {
            list.add(new HuffNode(value));
        }

        while (list.size() > 1) {
            Collections.sort(list);
            HuffNode leftNode = list.remove(0);
            HuffNode rightNode = list.remove(0);
            HuffNode root = new HuffNode(leftNode.value + rightNode.value);
            root.left = leftNode;
            root.right = rightNode;
            list.add(root);
        }
        return list.remove(0);
    }
	//对构建好的哈夫曼树进行先序遍历
    private static void preErgodic(HuffNode root) {
        if (root == null) {
            return;
        }
        System.out.print(root.value + "->");
        preErgodic(root.left);
        preErgodic(root.right);
    }

}
/**
*集成Comparable接口,实现其中的compareTo方法;方便后序使用Collections.sort进行排序
*/
class HuffNode implements Comparable<HuffNode> {
    public int value;	//结点的权值
    public HuffNode left;//结点的左指针
    public HuffNode right;	//结点的右指针

    public HuffNode(int value) {
        this.value = value;
    }
//this.value-o.value表示进行升序排序
    @Override
    public int compareTo(HuffNode o) {
        return this.value - o.value;
    }
}
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Thecoastlines

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

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

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

打赏作者

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

抵扣说明:

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

余额充值