哈夫曼树(郝夫曼树)及java实现

2022-03-28 20:23:34 浏览数 (1)

哈夫曼树是美国数学家Huffman发现的一种数据结构,该数据结构用在哈夫曼编码中,哈夫曼编码是一种压缩算法,本文主要针对的是哈夫曼树这种数据结构,哈夫曼编码将在下篇博文中涉及。

在正式开始了解哈夫曼树之前有几个概念需要了解:

1、路径长度:从树种一个节点到另一个节点间的分支构成两个节点之间的路径,路径上的分支数目就是路径长度,所以路径长度是针对两个节点间距离的一种描述,如下图所示,根节点到D节点的路径长度为4

2、如上图所示,如果考虑每条路径的权重,根节点到节点D的路径长度为4*30 = 120,即无权路径长度*该节点权重值

假设n个节点的权值为{w1,w2,...wn},这些节点对应的无权;路径长度为{l1,l2,...,ln},该树的带权路径长度WPL则为根节点到其他所有节点带权路径长度之和,即WPL=∑ wk*lk,k从1到n

3、WPL最小时对应的二叉树被称为哈夫曼树,也叫做最优二叉树。

有了上面的基础知识介绍,下面给出一种java实现:

代码语言:javascript复制
public class HuffmanTreeDemo {

    @Test
    public void test(){
        Queue<Node> q = new PriorityQueue<>();
        //先按照节点的权重进行降序排列
        q.add(new Node('A',20,null,null));
        q.add(new Node('G',10,null,null));
        q.add(new Node('s',34,null,null));
        q.add(new Node('K',16,null,null));
        q.add(new Node('x',8,null,null));
        q.add(new Node('q',5,null,null));
        //至少保证有两个节点,因为在组成树时需要两个
        while (q.size() >1){
            Node n1 = q.poll();
            Node n2 = q.poll();
            Node n = new Node(' ',n1.getWeight() n2.getWeight(),n1,n2);
            //将新形成的节点插入到队列中
            q.add(n);
        }
        //最后一个节点就是根节点
        Node root = q.poll();
        //打印哈夫曼树
        printHuffman(root);
    }

    /**
     * 采用前序遍历
     * @param node
     */
    private void printHuffman(Node node){
        if(node == null){
            return;
        }
        println(node.getWeight());
        printHuffman(node.getLeft());
        printHuffman(node.getRight());
    }
}


//节点
@Getter
public class Node implements Comparable<Node>{
    private char ch;
    private int weight;
    private final Node left;
    private final Node right;

    public Node(char ch,int weight,Node left,Node right){
        this.ch = ch;
        this.weight = weight;
        this.left = left;
        this.right = right;
    }

    public boolean isLeaf(){
        return left == null && right == null;
    }

    @Override
    public int compareTo(Node node){
        return this.weight - node.weight;
    }
}

拿上面这些数据来说明构造哈夫曼树的整个过程,如6个数,按照权重值进行排序后为5,8,10,16,20,34

然后根据排序抽出这些数据中最小的两个数,以这两个数作为左右子树构造新的父节点,该例子来说就是拿5和8两个节点,构造新的父节点13,然后将5,8,从待排序数组中删除,将新生成的13插入到队列中形成新的数组10,13,16,20,34,依次类推。

0 人点赞