哈夫曼树详解(上)

一、什么是哈夫曼树

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

二、哈夫曼树特点

哈夫曼树的特点:

  • 没有度为1的结点(每个非叶子结点都是由两个最小值的结点构成)
    n个叶子结点的哈夫曼树总共有2n-1个结点

  • n0:叶结点总数
    n1:只有一个儿子的结点总数 n2:有2个儿子的结点总数 n2=n0-1
    N=n0+n1+n2=2n-1

  • 哈夫曼树的任意非叶结点的左右子树交换后仍是哈夫曼树;

  • 对同一组权值{w1,w2,…},存在不同构的两个哈夫曼树,但是它们的总权值相等。

三、图的解析过程

  1. 第一步,给定一些数值,例如 : 1、4、8、16、32、64 在这里插入图片描述

2、找到最小的两个值,将他们的和构成一个新的节点
在这里插入图片描述
3、接下来就拿次小的数和刚刚组合出来的新节点,在重新组合,这样一次类推。
在这里插入图片描述
4、
在这里插入图片描述
5、
在这里插入图片描述
6、最后就形成了这样的一颗哈夫曼树,这也是二叉树的前序
在这里插入图片描述

四、代码实现


public class Node<T> implements Comparable<Node<T>> {
    private T data;
    private int height;
    private Node<T> left;
    private Node<T> right;

    public Node(T data,  int height) {
        this.data = data;
        this.height = height;
    }

    @Override
    public String toString() {
        return "Node:" + this.height;
    }

    @Override
    public int compareTo(Node<T> o) {
        if (o.height > this.height) {
            return 1;
        } else if (o.height < this.height) {
            return -1;
        }
        return 0;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public Node<T> getLeft() {
        return left;
    }

    public void setLeft(Node<T> left) {
        this.left = left;
    }

    public Node<T> getRight() {
        return right;
    }

    public void setRight(Node<T> right) {
        this.right = right;
    }

}

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

public class HuffmanTree<T> {

    public static <T> Node<T> createTree(List<Node<T>> nodes) {
        while (nodes.size() > 1) {
            // 这里直接用Java8已有的方法 sort排序
            // 但这个需要对应的实体类实现Comparable接口,重写compareTo自定规则比较
            Collections.sort(nodes);
            Node<T> left = nodes.get(nodes.size() - 1);
            Node<T> right = nodes.get(nodes.size() - 2);
            // 这里就是哈夫曼树的特点: 他的两个叶子节点之和等于他的父节点
            Node<T> parent = new Node<T>(null, left.getHeight()
                    + right.getHeight());
            parent.setLeft(left);
            parent.setRight(right);
            //删除原先两个权值最小的节点二叉树
            nodes.remove(left);
            nodes.remove(right);
            // 再添加最新的这个节点
            nodes.add(parent);
        }
        return nodes.get(0);
    }

    public static <T> List<Node<T>> breath(Node<T> root) {
        List<Node<T>> list = new ArrayList<Node<T>>();
        Queue<Node<T>> queue = new LinkedList<>();
        queue.add(root);
        while (!queue.isEmpty()) {
            // 这里就是利用Queue队列里的方法,移除第一个元素
            Node<T> pNode = queue.poll();
            list.add(pNode);
            if (pNode.getLeft() != null) {
                queue.add(pNode.getLeft());
            }
            if (pNode.getRight() != null) {
                queue.add(pNode.getRight());
            }
        }
        return list;
    }

}



```java

import java.util.ArrayList;
import java.util.List;

public class test {

    public static void main(String[] args) {
        List<Node<String>> nodes = new ArrayList<Node<String>>();
        nodes.add(new Node<String>("a", 1));
        nodes.add(new Node<String>("b", 4));
        nodes.add(new Node<String>("d", 16));
        nodes.add(new Node<String>("c", 8));
        nodes.add(new Node<String>("f", 64));
        nodes.add(new Node<String>("e", 32));
        Node<String> root = HuffmanTree.createTree(nodes);
        System.out.println(HuffmanTree.breath(root));
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值