当前位置:网站首页>(十二)树--哈夫曼树
(十二)树--哈夫曼树
2022-08-04 05:28:00 【顺毛黑起】
基本介绍
- 给定 n 个权值作为 n 个叶子结点,构造一棵二叉树,若该树的带权路径长度(wpl)达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。
- 赫夫曼树是带权路径长度最短的树,权值较大的结点离根较近
概念
- 路径和路径长度:在一棵树中,从一个结点往下可以达到的孩子或孙子结点之间的通路,称为路径。通路中分支的数目称为路径长度。若规定根结点的层数为 1,则从根结点到第 L 层结点的路径长度为 L-1
- 结点的权及带权路径长度:若将树中结点赋给一个有着某种含义的数值,则这个数值称为该结点的权。结点的带权路径长度为:从根结点到该结点之间的路径长度与该结点的权的乘积
- 树的带权路径长度:树的带权路径长度规定为所有叶子结点的带权路径长度之和,记为 WPL(weighted pathlength) ,权值越大的结点离根结点越近的二叉树才是最优二叉树。
- WPL 最小的就是哈夫曼树
构成哈夫曼树的步骤:
给定一个数列 {13, 7, 8, 3, 29, 6, 1},要求转成一颗赫夫曼树
package com.atguigu.huffmantree;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class HuffmanTree {
public static void main(String[] args) {
int[] arr={
13,7,8,3,29,6,1};
Node root=createHuffmanTree(arr);
preOrder(root);//
}
//前序遍历的方法
public static void preOrder(Node root){
if (root!=null){
root.preOrder();
}else {
System.out.println("是空树,不能遍历~~~");
}
}
//创建哈夫曼树的方法
public static Node createHuffmanTree(int[] arr){
//1.为了操作方便,遍历arr数组,将其中的每个元素构建成一个Node,将Node放入到ArrayList中
List<Node> nodes=new ArrayList<>();
for (int value:arr) {
nodes.add(new Node(value));
}
//处理的过程是一个循环的过程
while (nodes.size()>1){
//排序(从小到大)
Collections.sort(nodes);
System.out.println("nodes="+nodes);
//2 取出根节点权值最小的两棵二叉树
//(1)取出权值最小的结点(二叉树)
Node leftNode=nodes.get(0);
//(2)取出权值第二小的结点(二叉树)
Node rightNode=nodes.get(1);
//(3)构建一棵新的二叉树
Node parent=new Node(leftNode.value+rightNode.value);
parent.left=leftNode;
parent.right=rightNode;
//(4)从ArrayList中删除处理过的结点
nodes.remove(leftNode);
nodes.remove(rightNode);
//(5)将parent加入到ArrayList中
nodes.add(parent);
}
return nodes.get(0);
}
}
//创建结点类
//为了让Node对象持续排序Collections集合排序,让Node实现Comparable接口
class Node implements Comparable<Node>{
int value;//结点权值
Node left;//指向左子结点
Node right;//指向右子结点
//写一个前序遍历
public void preOrder(){
System.out.println(this);
if (this.left!=null){
this.left.preOrder();
}
if (this.right!=null){
this.right.preOrder();
}
}
public Node(int value){
this.value=value;
}
@Override
public String toString() {
return "Node{" +
"value=" + value +
'}';
}
@Override
public int compareTo(Node o) {
//this.value-o.value表示从小到大排序
return this.value-o.value;
}
}
边栏推荐
猜你喜欢
ReentrantLock(公平锁、非公平锁)可重入锁原理
Zend FrameWork RCE1
Kubernetes基本入门-集群资源(二)
ORACLE LINUX 6.5 安装重启后Kernel panic - not syncing : Fatal exception
The cost of automated testing is high and the effect is poor, so what is the significance of automated testing?
webrtc中视频采集实现分析(二) 视频帧的分发
登录页面js手写
PHP实现异步执行程序
iptables防火墙
VScode配置PHP环境
随机推荐
关于事件捕获和事件冒泡的顺序,以及如何处理事件冒泡带来的影响
跳转页面实时调用后台接口,更新页面数据
实际开发中,如何实现复选框的全选和不选
Kubernetes基础入门(完整版)
程序、进程、线程、协程的概念及区别
进程、线程、协程的区别和联系?
flink问题整理
关系型数据库-MySQL:二进制日志(binlog)
页面刷新没有执行watch?
自动化运维工具Ansible(5)流程控制
剑指 Offer 2022/7/9
完美解决keyby造成的数据倾斜导致吞吐量降低的问题
flink-sql所有表连接器
NFT市场开源系统
SQL练习 2022/7/1
数据库根据提纲复习
Code Refactoring: For Unit Testing
es6 学习记录
二月、三月校招面试复盘总结(一)
win云服务器搭建个人博客失败记录(wordpress,wamp)