文章目录
一、相关概念1.节点的路径及路径长度2.节点的带权路径长度3.树的带权路径长度4.霍夫曼树
二、构建步骤与图解1.构建步骤2.图解
三、代码实现1.创建节点类:2.创建霍夫曼树3.全部代码
一、相关概念
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
) {
nodes
.add(new Node(data
));
}
Node newNode
= null
;
while(nodes
.size() > 1){
Collections
.sort(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
);
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
);
}
}