一、相关概念
1.节点的路径及路径长度
路径:在树中,一个节点向下到达另一个节点的通路,称为路径。
路径长度:路径中经历的分支数。
在这里插入图片描述
图中节点1到节点4的路径就是:1->2,2->4。路径长度为2。
2.节点的带权路径长度
在树中,可以定义某个节点的权值,从根节点到此节点的路径长度与此节点的权值的乘积就是该节点的带权路径长度。
例如:上图中若定义节点4的权值为4,则其带权路径长度为4*2=8。
3.树的带权路径长度
树中所有叶子节点的带权路径之和称为树的带权路径长度,简称WPL(weighted path length)。
4.霍夫曼树
拥有相同叶子节点的所有树中,WPL最小的树称为霍夫曼树,又称最优二叉树。
在这里插入图片描述
上图中右面的就为霍夫曼树(未画出所有情况)。
二、构建步骤与图解
1.构建步骤
目标:给定一个数列arr,其中元素对应叶子节点的权值,以此构建霍夫曼树。
将数列中各元素看成只有根节点的树,按权值对各树从小到大排序。
以其中最小的两颗树为左右子树构建成一颗新的树t,t的权值为两子树权值之和。
在数列中用t取代其左右子树,再对剩下的树按权值进行排序,并循环1,2步骤。
直到数列中只剩下一个元素,霍夫曼树就构建成了。
2.图解
以arr={2,3,4,12,7,6}为例。
1.排序{2,3,4,6,7,12},并取出前两个。
在这里插入图片描述
2.变为{4,6,7,12,5},排序{4,5,6,7,12},取出前两个。
在这里插入图片描述
3.变为{6,7,12,9},排序{6,7,9,12},取出前两个。
在这里插入图片描述
4.变为{9,12,13},取出前两个。
在这里插入图片描述
4.变为{13,21},取出前两个。
在这里插入图片描述
5.4.变为{34},结束。
三、代码实现
1.创建节点类:
class Node implements Comparable<Node> {
int value;
Node left;
Node right;
public Node(int value) {
this.value = value;
}
@Override
public String toString() {
return "Node{" +
"value=" + value +
'}';
}
//排序需求
@Override
public int compareTo(Node o) {
return this.value - o.value;//从小到大排序
}
//前序遍历方法
public void preOrderTraversal(Node root){
if(root == null) return;
System.out.println(root);
preOrderTraversal(root.left);
preOrderTraversal(root.right);
}
}
2.创建霍夫曼树
public static Node huffmanTree(int[] arr){
List<Node> nodes = new ArrayList<>();
for (int data : arr) {//用arr建立多个node节点,存到nodes中
nodes.add(new Node(data));
}
Node newNode = null;
//构建霍夫曼树
while(nodes.size() > 1){
Collections.sort(nodes);
//System.out.println(nodes);
Node left = nodes.remove(0);
Node right = nodes.remove(0);
newNode = new Node(left.value + right.value);
newNode.left = left;
newNode.right = right;
nodes.add(newNode);
}
return newNode;
}
}
3.全部代码
public class HuffmanTree {
public static void main(String[] args) {
int[] arr = {2, 3, 4, 12, 7, 6};
Node root = huffmanTree(arr);
root.preOrderTraversal(root);
}
public static Node huffmanTree(int[] arr){
List<Node> nodes = new ArrayList<>();
for (int data : arr) {
nodes.add(new Node(data));
}
Node newNode = null;
while(nodes.size() > 1){
Collections.sort(nodes);
//System.out.println(nodes);
Node left = nodes.remove(0);
Node right = nodes.remove(0);
newNode = new Node(left.value + right.value);
newNode.left = left;
newNode.right = right;
nodes.add(newNode);
}
return newNode;
}
}
class Node implements Comparable<Node> {
int value;
Node left;
Node right;
public Node(int value) {
this.value = value;
}
@Override
public String toString() {
return "Node{" +
"value=" + value +
'}';
}
@Override
public int compareTo(Node o) {
return this.value - o.value;//从小到大排序
}
//前序遍历方法
public void preOrderTraversal(Node root){
if(root == null) return;
System.out.println(root);
preOrderTraversal(root.left);
preOrderTraversal(root.right);
}
}
本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责,本站只提供参考并不构成任何投资及应用建议。本站是一个个人学习交流的平台,网站上部分文章为转载,并不用于任何商业目的,我们已经尽可能的对作者和来源进行了通告,但是能力有限或疏忽,造成漏登,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。