赫夫曼树(哈夫曼树、霍夫曼树,最优二叉树)

一、赫夫曼树简介

1、简介

1)给定n个权值(节点的值)作为n个叶子结点,构造一棵二叉树,若该树的带权路径长度(wpl)达到最小,称这样的二叉树为 赫夫曼树(哈夫曼树、霍夫曼树,最优二叉树)。
2)赫夫曼树是带权路径长度最短的树,权值较大的结点离根较近

2、相关定义

1、路径:从一个节点往下可以到达子节点的之间的通路;
2、路径长度:通路中分支的数目。若规定跟节点所在的层数为1,则从根节点到第L层节点的路径长度为L-1;
3、节点的权:给树中的节点赋予一个有着某种含义的值;
4、节点的带权路径:从根结点到该结点之间的路径长度与该结点的权的乘积
5、WPL(weighted path length)树的带权路径长度:规定为所有叶子节点的带权路径长度之和。 权值越大的结点离根结点越近的二叉树才是最优二叉树。

WPL最小的树就是赫夫曼树:
在这里插入图片描述

二、赫夫曼树算法

1、算法思路

将数列 arr={12,3,5,8,34},转成一颗赫夫曼树,步骤如下:
1、从小到大对数组进行排序,将每个数值存入 ArrayList 链表,每个数值都是一个节点,每个节点可以看成一个最简单的二叉树。
2、从 ArrayList 取出根节点权值最小的两颗二叉树,组成一颗新的二叉树,该新的二叉树的根节点的权值就是前两颗二叉树根节点权值的和。
3、然后从 ArrayList 中将前两颗二叉树根节点remove,再把新的二叉树的根节点的权值放入 ArrayList 中,然后再次排序。
4、不断重复上述步骤,直到 ArrayList 中只剩下 赫夫曼树的根节点时退出循环,这样就可以得到一棵赫夫曼树了。

2、代码实现

import java.util.ArrayList;
import java.util.Collections;

/**
 * 哈夫曼树:最优二叉树
 */
public class HuffManTree {
   
    public static void main(String[] args) {
   
        int[] arr = {
   12,3,5,8,34};
        //生成赫夫曼树
        Node huffManTree = createHuffManTree(arr);
        //前序遍历赫夫曼树
        preOrder(huffManTree);
    }

    //创建赫夫曼树的方法
    public static Node createHuffManTree(int[] arr) {
   
//遍历arr数组,将arr的每个元素构建成一个NOde,将Node放入ArrayList;
        ArrayList<Node> nodes = new ArrayList<>();
        for (int value : arr) {
   
            nodes.add(new Node(value));

        }
//循环,直到ArrayList只剩一个节点时结束
        while (nodes.size() > 1) {
   
            //从大到小排序
            Collections.sort(nodes);
            //取出权值最小的两个节点(二叉树)
            Node leftNode = nodes.get(0);
            Node rightNode = nodes.get(1);

           //构建一个新的二叉树,左节点的值加上右节点的值等于父节点
            Node parent = new Node(leftNode.value + rightNode.value);
            parent.left = leftNode;
            parent.right = rightNode;

            //从ArrayList 删除处理过的节点

            nodes.remove(leftNode);
            nodes.remove(rightNode);
            //将父节点加入到ArrayList
            nodes.add(parent);
        }
//最后返回赫夫曼树的头就可以了
        return nodes.get(0);
    }
    
    //编写一个前序遍历的方法
    public  static  void preOrder(Node  root){
   
        if(root!=null){
   
            root.preOrder();
        }else {
   
            System.out.println("空树,无法遍历");
        }
    }
}
/**
 * 创建节点类
 * 为了让NOde对象支持排序COllectins 集合排序
 * 让Node 实现Comparable 接口
 */
class Node implements Comparable<Node> {
   
    int value;//节点权值
    Node left;//左子节点
    Node right;//右子节点
    //前序遍历
    public  void  preOrder(){
   
        System.out.println(this);
        if(this.left!=null){
   
            this.left.preOrder();
        }
        if(this.right!=null){
   
            this.right.preOrder();
        <
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值