哈夫曼树基础

[TOC]

基础概念

路径:

  • 在一棵树中,从一个结点到另一个结点所经过的所有结点,被我们称为两个结点之间的路径

v2-23615596f966a463cc267ed8c087502b_b.jpg

路径长度:

  • 在一棵树中,从一个结点到另一个结点所经过的“边”的数量,被我们称为两个结点之间的路径长度。

v2-406a6800d06e3e563ec5ff50d716832e_b.jpg

结点的带权路径长度:

  • 结点的带权路径长度,是指树的根结点到该结点的路径长度,和该结点权重的乘积。边数*权重

v2-d6e4a6781324aa5360cbcc2822375f8d_b.jpg

树的带权路径长度:

  • 在一棵树中,所有叶子结点的带权路径长度之和,被称为树的带权路径长度,也被简称为WPL。

v2-09976ac525c912bba5ed5e5ac698f3b0_b.jpg

哈夫曼树

  1. 就是保重树的带权路径长度最小。
  2. 哈夫曼树不唯一。
  3. 复杂度:nlog(n) 队列:log(n) 节点:n

实现逻辑

  1. ​ 借助辅助队列,由小到大入队列。
  2. 借助辅助队列,我们可以找到权值最小的结点2和3,并根据这两个结点生成一个新的父结点,父节点的权值是这两个结点权值之和。
  3. 从队列中移除上一步选择的两个最小结点,把新的父节点加入队列也就是从队列中删除2和3,插入5,并且仍然保持队列的升序。队列数据长度为一,结束。

图解

v2-3114ca8c32ed4516c6476ed305366a35_b.jpg

v2-7f5a908c94ec41c58b4bfa0f43104057_b.jpg

v2-782a054d52024345da6c607e017fb890_b.jpg

v2-d01b21bafe8f2ba1c576c03be9103340_b.jpg

v2-f784cf7f8814895f6570de756fc287c2_b.jpg

扫描二维码关注公众号,回复: 11063996 查看本文章
v2-dab0ea8d5bf402e3e1f13152d1ecaf25_b.jpg

v2-fbe88332f235c939e8a4d148568dc631_b.jpg

v2-dd52cc04bc3798459bf2487405c8e36d_b.jpg

v2-37350ebe2893583606ab22e0a54b0fbb_b.jpg

v2-0345ed8550082c3245ccb891d2dccf54_b.jpg

v2-786c07b20c65118a9f73acd511ce8960_b.jpg

v2-b390d96c16b35770300a2f8f88aad4db_b.jpg

代码实现

        package com.neusoft.data.structure;



//然后:实现哈夫曼树的主题类,其中包括两个静态的泛型方法,为创建哈夫曼树和广度优先遍历哈夫曼树


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

public class HuffmanTree<T> {
    public static <T> Node<T> createTree(List<Node<T>> nodes){
        //只要nodes数组中还有两个以上的节点
        while(nodes.size() > 1){
            Collections.sort(nodes);//1先排序数据
            // 获取权值最小的两个节点
            Node<T> left = nodes.get(nodes.size()-1);  //倒数第一个
            Node<T> right = nodes.get(nodes.size()-2);//倒数第二个
            //生成新节点,新节点的权值为两个子节点的权值之和
            Node<T> parent = new Node<T>(null, left.getWeight()+right.getWeight());
            //让新节点作为权值最小的两个节点的父节点
            parent.setLeft(left);
            parent.setRight(right);
            //删除权值最小的两个节点
            nodes.remove(left);
            nodes.remove(right);
            //将新生成的节点添加到集合中
            nodes.add(parent);
        }
        return nodes.get(0);
    }
    /*7 5 4 2
     *
     *       18
     *    11   7
     *   6  5
     *  2 4
     *
     *
     */

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        List<Node<String>> list = new ArrayList<Node<String>>();
        list.add(new Node<String>("a",7));
        list.add(new Node<String>("b",5));
        list.add(new Node<String>("c",4));
        list.add(new Node<String>("d",2));

        Node<String> root = HuffmanTree.createTree(list);
        System.out.println(HuffmanTree.breadth(root));
        //            System.out.println(list);
    }

    //广度优先遍历
    public static <T> List<Node<T>> breadth(Node<T> root){
        List<Node<T>> list = new ArrayList<Node<T>>();
        Queue<Node<T>> queue = new ArrayDeque<Node<T>>();

        if(root != null){
            //将跟元素入"队列"
            queue.offer(root);
        }

        while(!queue.isEmpty()){
            //将该队列的"队尾"的元素添加到list中
            list.add(queue.peek());
            Node<T> node = queue.poll();
            //如果左节点不为null,将它们加入队列
            if(node.getLeft() != null){
                queue.offer(node.getLeft());
            }
            //如果有节点不为null,将它们加入队列。
            if(node.getRight() != null){
                queue.offer(node.getRight());
            }
        }
        return list;
    }
}
class Node<T> implements Comparable<Node<T>> {
    private T data;
    private double weight;  //权重
    private Node<T> left;
    private Node<T> right;

    public Node(T data, double weight){
        this.data = data;
        this.weight = weight;
    }

    public T getData() {
        return data;
    }

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

    public double getWeight() {
        return weight;
    }

    public void setWeight(double weight) {
        this.weight = weight;
    }

    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;
    }

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

    @Override
    public int compareTo(Node<T> other) {
        if(other.getWeight() > this.getWeight()){
            return 1;
        }
        if(other.getWeight() < this.getWeight()){
            return -1;
        }

        return 0;
    }
}
      

输出

[data:null;weight:18.0, data:a;weight:7.0, data:null;weight:11.0, data:b;weight:5.0, data:null;weight:6.0, data:d;weight:2.0, data:c;weight:4.0]

发布了169 篇原创文章 · 获赞 18 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/yunfengfengfeng/article/details/105678804