哈夫曼树的介绍
Huffman Tree,中文名是哈夫曼树或霍夫曼树或者赫夫曼树,它是最优二叉树。
定义:给定n个权值作为n个叶子结点,构造一棵二叉树,若树的带权路径长度达到最小,则这棵树被称为哈夫曼树。
(01) 路径和路径长度
定义:在一棵树中,从一个结点往下可以达到的孩子或孙子结点之间的通路,称为路径。通路中分支的数目称为路径长度。若规定根结点的层数为1,则从根结点到第L层结点的路径长度为L-1。
(02) 结点的权及带权路径长度
定义:若将树中结点赋给一个有着某种含义的数值,则这个数值称为该结点的权。结点的带权路径长度为:从根结点到该结点之间的路径长度与该结点的权的乘积。
(03) 树的带权路径长度
定义:树的带权路径长度规定为所有叶子结点的带权路径长度之和,记为WPL。
————————————————
版权声明:本文为CSDN博主「liujc_love」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u012532559/article/details/44589997
哈夫曼树并不唯一,但带权路径长度一定是相同的。
(1)8个结点的权值大小如下:
(2)从19,21,2,3,6,7,10,32中选择两个权小结点。选中2,3。同时算出这两个结点的和5。
(3)从19,21,6,7,10,32,5中选出两个权小结点。选中5,6。同时计算出它们的和11。
(4)从19,21,7,10,32,11中选出两个权小结点。选中7,10。同时计算出它们的和17。
(BTW:这时选出的两个数字都不是已经构造好的二叉树里面的结点,所以要另外开一棵二叉树;或者说,如果两个数的和正好是下一步的两个最小数的其中的一个,那么这个树直接往上生长就可以了,如果这两个数的和比较大,不是下一步的两个最小数的其中一个,那么就并列生长。)
(5)从19,21,32,11,17中选出两个权小结点。选中11,17。同时计算出它们的和28。
(6)从19,21,32,28中选出两个权小结点。选中19,21。同时计算出它们的和40。另起一颗二叉树。
(7)从32,28, 40中选出两个权小结点。选中28,32。同时计算出它们的和60。
(8)从 40, 60中选出两个权小结点。选中40,60。同时计算出它们的和100。 好了,此时哈夫曼树已经构建好了。
————————————————
版权声明:本文为CSDN博主「阿伟_」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_33990383/article/details/53073825
代码实现
package com.yg.tree;/*
@author Mu_Mu
@date 2020/3/7 10:32
哈夫曼树
*/
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class HuffmanTree {
public static void main(String[] args) {
int []arr={1,5,9,8,4,2,3,7};
Node root = createHuffmanTree(arr);
preOrder(root);
}
//创建Huffman树
public static Node createHuffmanTree(int []arr) {
if (arr == null || arr.length == 0) {
return null;
}
List<Node>nodes=arrTransferToNodeList(arr);
while (nodes.size() > 1) {
Collections.sort(nodes);
Node leftNode=nodes.get(0);
Node rightNode=nodes.get(1);
//组合新的node
Node parent = new Node(leftNode.value + rightNode.value);
parent.left=leftNode;
parent.right=rightNode;
//删除原先的两个node,将新的node添加到list中
nodes.remove(leftNode);
nodes.remove(rightNode);
nodes.add(parent);
}
return nodes.get(0);
}
//将数组变为Node存入list集合中
public static List arrTransferToNodeList(int []arr){
List<Node>nodes=new ArrayList<Node>();
//将数组变为node节点存入list集合中方便后续排序
for (int value : arr) {
nodes.add(new Node(value));
}
return nodes;
}
//前序遍历
public static void preOrder(Node root) {
if (root == null) {
return;
}
root.preOrder();
}
}
class Node implements Comparable<Node> {
public int value;
public Node left;
public Node right;
public Node(int value) {
this.value = value;
}
//前序遍历
public void preOrder( ) {
System.out.println(this);
if (this.left != null) {
this.left.preOrder();
}
if (this.right != null) {
this.right.preOrder();
}
}
@Override
public String toString() {
return "Node{" +
"value=" + value +
'}';
}
@Override
public int compareTo(Node o) {
//从小到大
return this.value- o.value;
}
}