技术标签: 算法 Java基础学习系列 数据结构
我们的目标认识只是基础,代码实现是才是核心
从树中一个结点到另一个结点的之间的分支构成两个结点之间的路径,路径上的分支数称为路径长度。那么树的路径长度就是从树根到每一个结点的路径之和。带权路径长度WPL最小的二叉树叫做Huffman树。
二叉树的WPL = 5 * 3 + 15 * 3 + 40 * 2 + 30 * 2 + 10 * 2 = 220
这还不是一棵Huffman树,我们需要以下几个步骤
1.先把有权值的叶子结点按照从小到大的顺序排列成一个有序序列:A5,E10,B15,D30,E40.
2.取头两个最小权值的结点作为一个新节点N1的两个子节点,注意我们通常以相对较小的是左孩子,这里A就是N1的左孩子,E为N1的右孩子。新节点的权值为;两个叶子的权值和 5 + 10 = 10.
3.将N1替换成A与E,插入有序序列中,保持从小到大排列。即:N1(15),B15, D30,C40
4.重复2的操作,将N1和B作为一个新节点N2的两个子节点。
5.将N2替换N,与B,插入有序序列中,保持从小到大排列。即: N230, D30C40。
6.重复步骤2。将N2与D作为一个新节点N3的两个子结点。N3的权值=30+30=60。
7.将N3替换N2与D,插入有序序列中,保持从小到大排列。即: C40, N360。
8.重复步骤2。将C与Ngs作为1个新节点T的两个子结点。由于T即是根结点,完成赫夫曼树的构造。
此时带权路径长度 WPL = 40 * 1 + 30 * 2 + 15 * 3 + 10 * 4 +5 * 4 = 205 < 220 huffman树。
Huffman编码只需要把左孩子权值写成0,右孩子写成1,然后从根节点到叶子经过的路径就是它的编码。
A:1000 B:101 C:0 D:11 E:1001
package datastructure.tree;
import java.util.Collections;
import java.util.LinkedList;
import java.util.Scanner;
public class Huffman {
/** 用来存放节点值 */
private static LinkedList<HuffNode> huffList = new LinkedList<HuffNode>();
public static void main(String[] args) {
//输入数据
System.out.println("先输入数据个数回车,在输入数据");
System.out.println("请输入: ");
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
for (int i = 0; i < n; i++) {
//数据输入控制循环
huffList.add(new Huffman().new HuffNode(sc.next(),sc.nextInt() ));
}
huffmanCode();
decode(huffList.get(0), "");
}
class HuffNode implements Comparable<HuffNode> {
/** 权值 */
int value;
String name;
/** 左孩子节点 */
HuffNode lChild = null;
/** 右孩子节点 */
HuffNode rChild = null;
/*
* 构造方法,用于输入初始化Huffman结点
*/
public HuffNode(String name, int value) {
this.value = value;
this.name = name;
}
//构建Huffman树时的构造方法
public HuffNode(HuffNode lChild, HuffNode rChild) {
this.lChild = lChild;
this.rChild = rChild;
// 权值之和,即合并两个叶子节点
this.value = lChild.value + rChild.value;
}
/**********************
* @param next
* @param nextInt
*********************
*/
/**
* 重新写比较方法
*/
public int compareTo(HuffNode o) {
if (this.value < o.value) {
return -1;
} else if (this.value == o.value) {
return 0;
} else {
return 1;
}
}
}
//Huffman树构建和编码
public static void huffmanCode() {
/*
* 当所剩结点为一时构造Huffman树成功
* 否则执行循环直到Huffman树的结点为一结束
*/
if (huffList.size() == 1) {
return ;
}
while (huffList.size() > 1) {
// 排序
Collections.sort(huffList);
// 将前两个节点进行合并
HuffNode node = new Huffman().new HuffNode(huffList.get(0), huffList.get(1));
// 删除前两个节点
huffList.remove();
huffList.remove();
// 将新生成的节点添加到列表中
huffList.add(node);
}
// 编码完成后,此时huffList中只剩一个根节点
}
//解码方法,我们的编码是叶子结点,所以当左右孩子为空时就输出
public static void decode(HuffNode n, String code) {
if ((n.lChild == null) && (n.rChild == null)) {
// 叶子节点, 此时输出其对应编码
System.out.print(n.name + "--->" + code);
System.out.println();
return ;
}
// 遍历左子树
decode(n.lChild, code + "0");
// 遍历右子树
decode(n.rChild, code + "1");
return ;
}
}
测试数据:
5
A 5
B 15
C 40
D 30
E 10
运行结果:
文章浏览阅读6.1k次,点赞6次,收藏16次。总第442篇2021年 第012篇图数据结构,能够更好地表征现实世界。美团业务相对较复杂,存在比较多的图数据存储及多跳查询需求,亟需一种组件来对千亿量级图数据进行管理,海量图数据的高效存储..._美团点评 海量图片分布式图片存储的 底层技术
文章浏览阅读1.7k次。第一节 ElasticSearch概述1.1 ES 分布式的全文搜索引擎。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTfulweb接口。ElasticSearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。构建在全文检索开源软件Lucene之上的Elasticsear..._opensearch wildcard
文章浏览阅读1.3w次,点赞21次,收藏42次。防坑留名:为了避免以后自己遇到什么坑爹的东西,先留脚印给自己。这个hadoop呢,主要是可以让用户可以在不了解分布式底层细节的情况下,开发分布式程序,充分利用集群的威力进行高速运算和存储。这点比较厉害了。它主要是用来做数据分析,支持低端服务器集群(这点美滋滋- - ),先抓取大量数据,利用数据运算分析,获取日志,显示报表~~~~~;_hadoop3.0
文章浏览阅读801次。题目本题是中国海洋大学03-04年第二学期《C程序设计期中考试》第三题编程题的第三题。题目:编写求立方根函数double cube(double x);函数返回参数的立方根。主函数如下:。main() { double cube(double x); double x; scanf("%lf", &x); printf("cube(%lf)=%lf\n", cube(x));}以下是本篇文章正文内容,欢迎朋友们进行指正,一起探讨,共同进步。——来自考研路上的lwj一、解题_double cube(double x);
文章浏览阅读2.9k次,点赞2次,收藏14次。每台都做一做,然后记录在博客里.供自己和大家一起学习._lnhub hackthebox vulnstack vulntarget
文章浏览阅读1.1k次。Debian 6 安装小记07.31.2011 · Posted in LAMP上个月入手了mac,就把thinkpadr400冷落了蛮久。想着太浪费了,于是想着开始折腾系统。最开始是考虑unix中的freebsd, openbsd, netbsd,后来觉得还是回_linux pardus 6.1.0-17-amd64 #1 smp preempt_dynamic debian 6.1.69-1 (2023-12-
文章浏览阅读1.2k次,点赞4次,收藏2次。互联网公司在缓存架构上是区分很大的,往往是根据企业的业务量来进行选择的,可以看如下图在传统的小型互联网公司,采用网页静态化技术,freemarker来加快用户的体验速度,从来来提升响应,但是如果出现了缓存血崩,缓存击穿那么对数据库将会造成很大的压力,可能导致整个架构无法使用一 缓存击穿 缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数据则不写..._缓存框架的原理
文章浏览阅读1.1k次,点赞2次,收藏3次。首先了解一下可变参数#include <stdio.h> #define DEBUG(fmt, ...) printf(fmt, __VA_ARGS__)int main(){ DEBUG("you know i am handsome%d,%f,%d", 1000, 1.1, 10); return 0;}输出:you know i am handsome1000,1.100000,10这里的__VA_ARGS__其实就是指代…三个省略号的内容了,这_##__va_args__
文章浏览阅读9.3k次。下面是vue实现,原生html后续贴上来前期准备:引入amap、echarts、echarts-amap依赖,vue的话需要npm安装一下By using script tag<!--引入高德地图JSAPI --> <script src="//webapi.amap.com/maps?v=1.4.15&key=ab99f68b8f9eac7a5287f..._import echartsamap from "echarts-amap";
文章浏览阅读574次。The flowable.form.cfg.xml must contain a bean that has the id ‘formEngineConfiguration’.这个flowable.form.cfg.xml必须包含id为“formEngineConfiguration”的bean。 <bean id="formEngineConfiguration" class="org.flowable.form.engine.impl.cfg.StandaloneFormEngineConfi_form engine is not initialized
文章浏览阅读4.6k次,点赞2次,收藏12次。首先说明,yocto中的依赖本质上是任务之间的依赖,即使是使用DEPENDS或者RDEPENDS定义的两个recipe之间的依赖关系,但实际上在yocto运行时依赖关系还是会体现在这两个recipe中的task之间,即在运行时,yocto会将recipe之间的依赖解析成task之间的依赖。task之间的依赖关系可以分为两种:属于同一个recipe的task之间的依赖或者属于不同recipe的ta..._yocto depends
文章浏览阅读162次。当一个Web系统从日访问量10万逐步增长到1000万,甚至超过1亿的过程中,Web系统承受的压力会越来越大,在这个过程中,我们会遇到很多的问题。为了解决这些性能压力带来问题,我们需要在Web系统架构层面搭建多个层次的缓存机制。在不同的压力阶段,我们会遇到不同的问题,通过搭建不同的服务和架构来解决。Web负载均衡Web负载均衡(Load Balan