霍夫曼树详解Java数据结构篇

霍夫曼树

定义:给定N个权值作为N个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为赫夫曼树(Huffman Tree)。什么赫夫曼树,霍夫曼树都是翻译的不同产物罢了;
路径:从一个节点到另一个节点的通路称为路径;
路径的长度:路径中通过节点两两连线的个数即为路径长度;
:节点中的值即为权;
带权路径长度:路径长度*权=带权路径长度
树的带权路径长度:所有叶子节点的带权路径长度之和,记为WPL(由此可见权值大的,离根节点越近的越优)
赫夫曼树:WPL最小的树

下面的方法为:将该数组 arr={14,9,10,5,29,7,2} 化为Huffman树
在这里插入图片描述

代码:
>思路:
  给定一个数组,将其写成赫夫曼树

>步骤:
1. 创建一个结合,用于存放入节点
2. 将数组的每一项创建成一个节点(每一项的值为该节点的权)
3. 对每个节点的权进行比较(实现Comparable接口的方法,调用工具类Collections的sort方法)
4. 得到权值有序的集合
5. 得到集合的第0项和第一项的权值之和,并创建该权值的节点,称之为父节点,并将父节点add到集合中
6. 将第0项和第一项分别设置为父节点的左右子节点,并remove这两个子节点
7. 将新的集合排序(Collections的sort方法)
8. 然后继续上面的操作,直到只剩下一个节点
9. 此时以该节点为根节点对应的树,即为Huffman树
10. 此时对该节点进行前序遍历

节点类:

public class Node implements Comparable<Node> {
    int value;
    Node left;
    Node right;

    public Node(int value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return "Node{" +
                "value=" + value +
                '}';
    }

    @Override
    public int compareTo(Node o) {
        //this.value-o.value:添加的node按照从小到大的顺序
        return this.value-o.value;
    }
}

操作类:

public class HuffmanTree {
    public static void main(String[] args) {
        int[] arr={14,9,10,5,29,7,2};
        Node huffman = huffman(arr);//得到赫夫曼树的根节点
        perOrder(huffman);//打印出赫夫曼树的前序遍历
    }
    //得到赫夫曼树,该方法返回赫夫曼树的根节点
    public static Node huffman(int[] arr){
        ArrayList<Node> nodes = new ArrayList<>();
        for (int value : arr) {
            nodes.add(new Node(value));
        }
        while (nodes.size()>1) {
            Collections.sort(nodes);//将nodes排序
            Node leftNode = nodes.get(0);
            Node rightNode = nodes.get(1);
            Node parent = new Node(leftNode.value + rightNode.value);
            nodes.add(parent);
            parent.left = leftNode;
            parent.right = rightNode;
            nodes.remove(leftNode);
            nodes.remove(rightNode);
        }
        return nodes.get(0);
    }
    //前序遍历,传入赫夫曼的根节点,返回赫夫曼树的前序遍历
    public static void perOrder(Node node){
        System.out.println(node);
        if (node.left!=null){
            perOrder(node.left);
        }
        if (node.right!=null){
            perOrder(node.right);
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值