哈弗曼树的理解和实现(Java)
哈弗曼树概述
哈弗曼树又称最优树,是一种带权路径长度最短的树,在实际中有广泛的用途。哈弗曼树的定义,涉及路径、路径长度、权等概念。哈弗曼树可以用于哈弗曼编码,用于压缩,用于密码学等。
哈弗曼树的一些定义
路径:从树中的一个结点到另一个结点之间的分支构成这两个结点的路径,
路径长度:路径上的分支数目称为路径长度。
树的路径长度:从树根到每一个结点的路径长度之和,我们所说的完全二叉树就是这种路径长度最短的二叉树。
权:赋予某个实体一个量,是对实体的某个或某些属性的数值化描述。
节点的带权路径长度:从该节点到树根之间的路径长度与节点上权的乘积。
树的带权路径长度:如果在树的每一个叶子结点上赋上一个权值,那么树的带权路径长度就等于根结点到所有叶子结点的路径长度与叶子结点权值乘积的总和。
最优二叉树:从已给出的目标带权结点(单独的结点) 经过一种方式的组合形成一棵树.使树的权值最小.。最优二叉树是带权路径长度最短的二叉树。根据结点的个数,权值的不同,最优二叉树的形状也各不相同。它们的共同点是:带权值的结点都是叶子结点。权值越小的结点,其到根结点的路径越长。

他们的带权长度分别为:
WPL1:7*2+5*2+2*2+4*2=36
WPL2:7*3+5*3+2*1+4*2=46
WPL3:7*1+5*2+2*3+4*3=35
所以,第三棵树的带权路径最短。
构造哈弗曼树
1) 根据给定的n个权值{w1, w2, w3, w4......wn}构造n棵只有根节点的二叉树,这n棵二叉树构成一个森林F。
2) 在森林F中选择两棵根节点的权值最小的二叉树,作为一棵新的二叉树的左右子树,且令新的二叉树的根节点的权值为其左右子树的权值和;
3)从F中删除被选中的那两棵子树,并且把构成的新的二叉树加到F森林中;
4)重复2 ,3 操作,直到森林只含有一棵二叉树为止,此时得到的这棵二叉树就是哈夫曼树。

代码实现(Java)
节点类:
package 哈弗曼树;
public class HuffmanNode {
private Object data;
private int weight;
private HuffmanNode lChild;
private HuffmanNode rChild;
public HuffmanNode() {
this.data = null;
this.weight = 0;
this.lChild = null;
this.rChild = null;
}
public HuffmanNode(Object data, int weight) {
this.data = data;
this.weight = weight;
}
public HuffmanNode(int weight, HuffmanNode lChild, HuffmanNode rChild) {
this.weight = weight;
this.lChild = lChild;
this.rChild = rChild;
}
public HuffmanNode(Object data, int weight, HuffmanNode lChild, HuffmanNode rChild) {
this.data = data;
this.weight = weight;
this.lChild = lChild;
this.rChild = rChild;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
public HuffmanNode getlChild() {
return this.lChild;
}
public void setlChild(HuffmanNode lChild) {
this.lChild = lChild;
}
public HuffmanNode getrChild() {
return this.rChild;
}
public void setrChild(HuffmanNode rChild) {
this.rChild = rChild;
}
}
哈弗曼树类:
package 哈弗曼树;
import java.util.ArrayList;
public class HuffmanTree {
private String str = "";
private HuffmanNode root;
private ArrayList<String> charList;
private ArrayList<HuffmanNode> nodeList;
private boolean flag;
//构造哈弗曼树
public void createHuffmanTree(String str) {
this.str = str;
charList = new ArrayList<String>();
nodeList = new ArrayList<HuffmanNode>();
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
flag = true;
for (int j = 0; j < charList.size(); j++) {
if(charList.get(j).charAt(0) == ch) {
String s = charList.get(j) + ch;
charList.set(j, s);
flag = false;
break;
}
}
if(flag) {
charList.add(charList.size(), ch + "");
}
}
for (int i = 0; i < charList.size(); i++) {
Object data = charList.get(i).charAt(0);
int weight = charList.get(i).length();
HuffmanNode node = new HuffmanNode(data, weight);
nodeList.add(node);
}
while(nodeList.size() > 1) {
this.sortOrder(nodeList);
HuffmanNode left = nodeList.remove(0);
HuffmanNode right = nodeList.remove(0);
int parentWeight = left.getWeight() + right.getWeight();
HuffmanNode parent = new HuffmanNode(null, parentWeight, left, right);
nodeList.add(parent);
}
root = nodeList.get(0);
}
//升序排序
private void sortOrder(ArrayList<HuffmanNode> nodeList) {
for (int i = 0; i < nodeList.size() - 1; i++) {
for (int j = i + 1; j < nodeList.size(); j++) {
HuffmanNode node;
if(nodeList.get(i).getWeight() > nodeList.get(j).getWeight()) {
node = nodeList.get(i);
nodeList.set(i, nodeList.get(j));
nodeList.set(j, node);
}
}
}
}
//中序遍历二叉树
public void print() {
output(root);
}
private void output(HuffmanNode root) {
if(root != null) {
System.out.print(root.getData() + " , ");
output(root.getlChild());
output(root.getrChild());
}
}
public static void main(String[] args) {
HuffmanTree tree = new HuffmanTree();
tree.createHuffmanTree("aabbbcccc");
tree.print();
}
}
哈弗曼树的理解和实现(Java)的更多相关文章
- java实现哈弗曼树
O(∩_∩)O~~ 概述 我想学过数据结构的小伙伴一定都认识哈弗曼,这位大神发明了大名鼎鼎的“最优二叉树”,为了纪念他呢,我们称之为“哈弗曼树”.哈弗曼树可以用于哈弗曼编码,编码的话学问可就大了,比如 ...
- java实现哈弗曼树和哈夫曼树压缩
本篇博文将介绍什么是哈夫曼树,并且如何在java语言中构建一棵哈夫曼树,怎么利用哈夫曼树实现对文件的压缩和解压.首先,先来了解下什么哈夫曼树. 一.哈夫曼树 哈夫曼树属于二叉树,即树的结点最多拥有2个 ...
- K:哈弗曼树
相关介绍: 树形结构除了应用于查找和排序等操作时能调高效率,它在信息通讯领域也有着广泛的应用.哈弗曼(Huffman)树就是一种在编码技术方面得到广泛应用的二叉树,它同时也是一种最优二叉树. 哈弗曼 ...
- HDU2527:Safe Or Unsafe(哈弗曼树)
Problem Description Javac++ 一天在看计算机的书籍的时候,看到了一个有趣的东西!每一串字符都可以被编码成一些数字来储存信息,但是不同的编码方式得到的储存空间是不一样的!并且当 ...
- SLT 优先队列 哈弗曼树最小带权路径
与普通的队列不同,普通的队列是先进先出的,而优先队列出队的顺序不是先进先出,而是大(或者小)元素先出队,需要#include <queue> 成员函数 成员函数 作用 empty() 判断 ...
- PKU 1521 Entropy(简单哈弗曼树_水过)
题目大意:原题链接 给你一个字符串,首先是计算出一个按正常编码的编码长度,其次是计算出一个用霍夫曼编码的编码长度,最后求正常编码的长度除以霍夫曼编码长度的比值,保留一位小数. 解题思路:需要知道 1. ...
- POJ 3253 Fence Repair(简单哈弗曼树_水过)
题目大意:原题链接 锯木板,锯木板的长度就是花费.比如你要锯成长度为8 5 8的木板,最简单的方式是把21的木板割成13,8,花费21,再把13割成5,8,花费13,共计34,当然也可以先割成16,5 ...
- Python 数据结构与算法 —— 哈弗曼树
1. 从扩充二叉树到哈弗曼树 扩充二叉树:对二叉树 T,加入足够多的新叶节点(而不是任意),使 T 的原有结点都变成度数为 2 的分支节点,得到的二叉树称为 T 的扩充二叉树. 对于扩充二叉树而言, ...
- POJ 3253 Fence Repair【哈弗曼树/贪心/优先队列】
Fence Repair Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 53645 Accepted: 17670 De ...
随机推荐
- python在windows环境安装MySQLdb
一.环境 系统:win7,64位 python版本:2.7.15 pip版本:10.0.1 二.安装 1. 用pip安装 pip install MySQLdb 报错: Could not find ...
- c语言define和typedef区别和使用
define完全可以理解替换,typedef代表别名.听着差不多的意思,那2者区别在哪? 先来个简单例子查看基本使用. //define和typedef区别 #define DB double //替 ...
- smarty foreach
<{foreach from=$data item=val }> <tr align="center"> <td><{$val.item_ ...
- qt4代码到qt5代码出错
1.error C2039: “toAscii”: 不是“QString”的成员 QT5.0.1把这个函数取消掉了,可以用toLatin1这个函数
- http://4526621.blog.51cto.com/4516621/1343369
http://4526621.blog.51cto.com/4516621/1343369
- HDU 1286 找新朋友 (欧拉phi函数打表)
题意:你懂得. 析:一看这个题应该是欧拉phi函数,也就说欧拉phi函数是指求从 1 到 n 中与 n 互素的数的个数,这个题很明显是这个意思嘛,不多说了. 代码如下: #include <io ...
- iOS隐藏导航条1px的底部横线
第二种方法:1)声明UIImageView变量,存储底部横线 @implementation MyViewController { UIImageView *navBarHairlineImageVi ...
- 寻找最大的K个数(下)
接着昨天的写,里面的代码包含昨天的 #include <iostream> using namespace std; #define N 50 //初始化数组 , , , , , , , ...
- SqlerMonitor-复制
在复制系统中因为一些配置上失误和人为的失误操作导致复制堵塞,Sqler Monitor 新增加了分析复制延迟邮件,配合复制错误监控邮件和延迟邮件,和复制元数据采集 可以在第一时间准确定位到问题,适合大 ...
- mysql多个TimeStamp设置(转)
timestamp设置默认值是Default CURRENT_TIMESTAMP timestamp设置随着表变化而自动更新是ON UPDATE CURRENT_TIMESTAMP 但是由于 一个表中 ...