package com.ietree.basic.datastructure.tree;

 import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue; /**
* Created by ietree
* 2017/5/1
*/
public class HuffmanTree { public static class Node<E> {
E data;
double weight;
Node leftChild;
Node rightChild; public Node(E data, double weight) {
this.data = data;
this.weight = weight;
} public String toString() {
return "Node[data=" + data + ", weight=" + weight + "]";
}
} public static void main(String[] args) { List<Node> nodes = new ArrayList<Node>();
nodes.add(new Node("A", 40));
nodes.add(new Node("B", 8));
nodes.add(new Node("C", 10));
nodes.add(new Node("D", 30));
nodes.add(new Node("E", 10));
nodes.add(new Node("F", 2)); Node root = HuffmanTree.create(nodes);
System.out.println(breadthFirst(root)); } /**
* 构造哈夫曼树
*
* @param nodes 节点集合
* @return 构造出来的哈夫曼树的根节点
*/
private static Node create(List<Node> nodes) { // 只要nodes数组中还有2个以上的节点
while (nodes.size() > 1) {
quickSort(nodes);
// 获取权值最小的两个节点
Node left = nodes.get(nodes.size() - 1);
Node right = nodes.get(nodes.size() - 2);
// 生成新节点,新节点的权值为两个子节点的权值之和
Node parent = new Node(null, left.weight + right.weight);
// 让新节点作为权值最小的两个节点的父节点
parent.leftChild = left;
parent.rightChild = right;
// 删除权值最小的两个节点
nodes.remove(nodes.size() - 1);
nodes.remove(nodes.size() - 1);
// 将新生成的父节点添加到集合中
nodes.add(parent);
}
// 返回nodes集合中唯一的节点,也就是根节点
return nodes.get(0);
} // 将指定数组的i和j索引处的元素交换
private static void swap(List<Node> nodes, int i, int j) {
Node tmp;
tmp = nodes.get(i);
nodes.set(i, nodes.get(j));
nodes.set(j, tmp);
} // 实现快速排序算法,用于对节点进行排序
private static void subSort(List<Node> nodes, int start, int end) { // 需要排序
if (start < end) {
// 以第一个元素作为分界值
Node base = nodes.get(start);
// i从左边搜索,搜索大于分界值的元素的索引
int i = start;
// j从右边搜索,搜索小于分界值的元素的索引
int j = end - 1;
while (true) {
// 找到大于分界值的元素的索引,或者i已经到了end处
while (i < end && nodes.get(++i).weight >= base.weight) ;
// 找到小于分界值的元素的索引,或者j已经到了start处
while (j > start && nodes.get(--j).weight <= base.weight) ;
if (i < j) {
swap(nodes, i, j);
} else {
break;
}
}
swap(nodes, start, j);
// 递归左子树序列
subSort(nodes, start, j - 1);
// 递归右子树序列
subSort(nodes, j + 1, end);
}
} public static void quickSort(List<Node> nodes) {
subSort(nodes, 0, nodes.size() - 1);
} // 广度优先遍历
public static List<Node> breadthFirst(Node root) { Queue<Node> queue = new ArrayDeque<Node>();
List<Node> list = new ArrayList<Node>();
if (root != null) {
// 将根元素入“队列”
queue.offer(root);
}
while (!queue.isEmpty()) {
// 将该队列的“队尾”的元素添加到List中
list.add(queue.peek());
Node p = queue.poll();
// 如果左子节点不为null,将它加入“队列”
if (p.leftChild != null) {
queue.offer(p.leftChild);
}
// 如果右子节点不为null,将它加入“队列”
if (p.rightChild != null) {
queue.offer(p.rightChild);
}
}
return list; } }

Java中的哈夫曼树的更多相关文章

  1. word2vec中关于霍夫曼树的

    再谈word2vec 标签: word2vec自然语言处理NLP深度学习语言模型 2014-05-28 17:17 16937人阅读 评论(7) 收藏 举报  分类: Felven在职场(86)    ...

  2. 2018.2.14 Java中的哈夫曼编码

    概念 哈夫曼编码(Huffman Coding),又称霍夫曼编码,是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种.Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造 ...

  3. 哈夫曼树的介绍 ---java实现

    一.     什么是哈夫曼树 是一种带权路径长度最短的二叉树,也称最优二叉树 带权路径长度:WPL=(W1*L1+W2*L2+W3*L3+...+ Wn*Ln) N个权值Wi(i=1,2,...n)构 ...

  4. 高级数据结构---赫(哈)夫曼树及java代码实现

    我们经常会用到文件压缩,压缩之后文件会变小,便于传输,使用的时候又将其解压出来.为什么压缩之后会变小,而且压缩和解压也不会出错.赫夫曼编码和赫夫曼树了解一下. 赫夫曼树: 它是一种的叶子结点带有权重的 ...

  5. Java 树结构实际应用 二(哈夫曼树和哈夫曼编码)

     赫夫曼树 1 基本介绍 1) 给定 n 个权值作为 n 个叶子结点,构造一棵二叉树,若该树的带权路径长度(wpl)达到最小,称这样的二叉树为 最优二叉树,也称为哈夫曼树(Huffman Tree), ...

  6. 【算法】赫夫曼树(Huffman)的构建和应用(编码、译码)

    参考资料 <算法(java)>                           — — Robert Sedgewick, Kevin Wayne <数据结构>       ...

  7. 数据结构图文解析之:哈夫曼树与哈夫曼编码详解及C++模板实现

    0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...

  8. (哈夫曼树)HuffmanTree的java实现

    参考自:http://blog.csdn.net/jdhanhua/article/details/6621026 哈夫曼树 哈夫曼树(霍夫曼树)又称为最优树. 1.路径和路径长度在一棵树中,从一个结 ...

  9. 哈夫曼树(三)之 Java详解

    前面分别通过C和C++实现了哈夫曼树,本章给出哈夫曼树的java版本. 目录 1. 哈夫曼树的介绍 2. 哈夫曼树的图文解析 3. 哈夫曼树的基本操作 4. 哈夫曼树的完整源码 转载请注明出处:htt ...

随机推荐

  1. 判断gridView是否有数据

    我这里的gridView是采用空模板数据来显示的 当gridView的数据源为空的时候它们就会显示标题 有数据的显示它们就会显示下面的这种 你仔细观察会发现,当有数据的时候空标题的table没有了,解 ...

  2. Android学习笔记36:使用SQLite方式存储数据

    在Android中一共提供了5种数据存储方式,分别为: (1)Files:通过FileInputStream和FileOutputStream对文件进行操作.具体使用方法可以参阅博文<Andro ...

  3. redis的使用和安装,redis基础和高级部分

    redis的使用和安装,redis基础和高级部分 在后端开发中,为了提高性能,对于一些经常查询但是又不太变化的内容会使用redis,比如前端的列表展示项等,如果数据有变化也可以清空缓存,让前端查一次数 ...

  4. linux 远端执行shell脚本 批量结束各个远端节点进程

    #以下是一个本地的shell脚本,用于同时重启远端多台服务器tomcat服务 #!/bin/sh# ancyshi 重新启动节点tomcat服务function restartNodeTomcatSe ...

  5. spring配置文件头部配置解析

    http://blog.csdn.net/f_639584391/article/details/50167321

  6. a &a &a[0]之间的区别和联系

    数组中,a为数组的首地址,&a[0]为数组第一个元素的地址. 所以 a == &a[0] 但是,&a又是什么东西呢? 我们来做下面的代码测试: #include <std ...

  7. DML语句报错是因为控制文件无法扩大还是另有原因?

    今天处理了一个很有意思的故障问题,来龙去脉是这种: 客户来电咨询控制文件无法扩展,数据库仅仅能查询但不支持DML,须要远程支持.接到电话的第一反应就是CONTROL_FILE_RECORD_KEEP_ ...

  8. Hadoop1.2.1 日志格式说明及启停方式

    日志格式: 日志名称解析: Hadoop启停的三种方式: . 停止后面的以此类推...... 另外 hadoop-daemons.sh 表示启动多个,比如datanode跟tasktracker在真实 ...

  9. kotlin 遇到的问题

    转载请表明 https://i.cnblogs.com/EditPosts.aspx?opt=1 从5月18号goole正式公布用kotlin做为android的新语言,做为android也很庆幸可以 ...

  10. 使用JSP表达式和JSP脚本打印九九乘法表

    首先使用JSP声明声明一个函数用于得到九九乘法表的内容 <%! String printMultiTable() { String s = ""; for (int i = ...