霍夫曼树
基本介绍
-
又称哈夫曼树,赫夫曼树
-
给定n个权值作为n个叶子节点,构造一棵二叉树,若该树的带权路径长度(wpl)达到最小,称为最优二叉树
-
霍夫曼树是带权路径长度最短的树,权值较大的节点离根较近
几个重要的概念
-
路径和路径长度:一棵树中从一个节点往下可以达到的子节点之间的通路叫做路径,通路中分支的数目称为路径长度。如规定根节点的层数为1,则从根节点到L层节点的路径长度为L - 1
-
节点的权及带权路径长度:若将书中的节点赋值给一个有着某种含义的数值,则这个数值称为节点的权,带权路径长度为路径与权值的成绩
-
树的带权路径长度:所有叶子节点的带权路径长度之和,记为WPL,权值越大的节点离根节点越近的二叉树才是最优二叉树
-
WPL最小的就是霍夫曼树
举例说明:
创建霍夫曼树
-
将数据从小到大排序,每个数据看成一个节点,每个节点是最简单的二叉树
-
取出根节点权值最小的两颗二叉树
-
组成一棵新的二叉树,该新的二叉树的根节点的权值是前面两颗二叉树根节点权值之和
-
再将这颗心的二叉树,以根节点的权值大小再次排序,不断重复上述步骤
-
直到数列中,所有的数据都被处理就得到一棵霍夫曼树
创建霍夫曼树的过程图解
-
数据为:{13,7,8,3,29,6,1}
-
排序:{1,3,6,7,8,13,29}
-
取出1,3创建,根节点权值为两节点权值之和,数据:{4,6,7,8,13,29}
-
处理4,6,数据:{7,8,10,13,29}
-
后面依次处理剩余数据……直到所有数据处理完毕
代码实现创建霍夫曼树
package com.why.tree;
import javax.swing.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* @Description TODO 创建霍夫曼树
* @Author why
* @Date 2020/11/28 13:23
* Version 1.0
**/
public class HuffmanTreeDemo {
public static void main(String[] args) {
int[] arr = {13,7,8,3,29,6,1};
HuffmanNode root = creatHuffmanTree(arr);
preOrder(root);
}
/**
* 创建霍夫曼树
* @param arr
* @return
*/
public static HuffmanNode creatHuffmanTree(int[] arr){
//构建Node,装入list
List<HuffmanNode> list = new ArrayList<>();
for (int i = 0; i < arr.length; i++) {
list.add(new HuffmanNode(arr[i]));
}
//从小到大排序
Collections.sort(list);
//循环处理
while (list.size() > 1){
//取出权值最小的两个二叉树
HuffmanNode left = list.get(0);
HuffmanNode right = list.get(1);
//构建新的二叉树
HuffmanNode root = new HuffmanNode(left.value+right.value);
root.left = left;
root.right = right;
//从list中删除处理过的二叉树
list.remove(left);
list.remove(right);
//将root加入list
list.add(root);
//重新排序
Collections.sort(list);
}
return list.get(0);
}
public static void preOrder(HuffmanNode root){
if (root != null){
root.preOrder();
}else {
System.out.println("空树");
}
}
}
/**
* 创建节点类
* 为了让Node对象支持Collections排序,让Node实现Comparable接口