Java---Huffman树的实现
Posted 坦荡的火星
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java---Huffman树的实现相关的知识,希望对你有一定的参考价值。
什么是哈弗曼树
1.哈弗曼树是最优二叉树,树的带权路径长度最小的一个二叉树。
2.带权路径长度为根节点到该节点的路径长度和该节点权重的乘积。
3.路径长度为当前节点到另一个节点所经过的分支的个数(边的个数)。
应用场景
哈弗曼树可以用来求哈弗曼编码,通过对文件中不同数据出现的频率,
设计出新的编码方式,来对文件进行数据压缩。
建立哈弗曼树
1.将表示不同数据的节点按照出现的频率(权重)进行排序。
2.选取出两个最小频率(权重)的数据,创建新节点,作为新节点的两个子节点。
3.将两个子节点从原有的节点集删除,计算新节点的权重,并将其加入到节点集合中。
4.对新的节点集进行排序,重复2和3步骤,直到节点集中只有一个节点。
代码实现
package com.newer.tree;
/**
* 哈弗曼树中每个节点的信息
*
* @author lixiaochi
*
*/
public class HuffmaNode {
// 当前节点的数据
String name;
// 当前节点的权重
int value;
// 当前节点所对应的哈弗曼编码
String encode;
// 当前节点的左右子节点
HuffmaNode leftChild;
HuffmaNode rightChild;
// Hafuman节点的构造方法
public HuffmaNode(String name, int value) {
super();
this.name = name;
this.value = value;
}
public HuffmaNode(String name, int value, HuffmaNode leftChild, HuffmaNode rightChild) {
super();
this.name = name;
this.value = value;
this.leftChild = leftChild;
this.rightChild = rightChild;
}
@Override
public String toString() {
return "HuffmaNode [name=" + name + ", value=" + value + ", encode=" + encode + "]";
}
}
package com.newer.tree;
/**
* 我的哈弗曼树
* 什么是哈弗曼树:哈弗曼树是最优二叉树,树的带权路径长度最小的一个二叉树。
* 带权路径长度为根节点到该节点的路径长度和该节点权重的乘积。
* 路径长度为当前节点到另一个节点所经过的分支的个数(边的个数)。
*
* 应用场景:哈弗曼树可以用来求哈弗曼编码,通过对文件中不同数据出现的频率,
* 设计出新的编码方式,来对文件进行数据压缩。
* 建立哈弗曼树:
* 1.将表示不同数据的节点按照出现的频率(权重)进行排序。
* 2.选取出两个最小频率(权重)的数据,创建新节点,作为新节点的两个子节点。
* 3.将两个子节点从原有的节点集删除,计算新节点的权重,并将其加入到节点集合中。
* 4.对新的节点集进行排序,重复2和3步骤,直到节点集中只有一个节点。
*
* @author lixiaochi
*
*/
public class MyHuffmanTree {
// 哈弗曼树的根节点
HuffmaNode root;
public static void main(String[] args) {
MyHuffmanTree huffmantree = new MyHuffmanTree();
// 数组中的元素是一个节点,节点中有数据内容和出现的频率。
HuffmaNode[] nodeArray = new HuffmaNode[6];
// 哈弗曼树中各个节点的初始化。
nodeArray[0]=new HuffmaNode("A",27);
nodeArray[1]=new HuffmaNode("B",8);
nodeArray[2]=new HuffmaNode("C",15);
nodeArray[3]=new HuffmaNode("D",15);
nodeArray[4]=new HuffmaNode("E",30);
nodeArray[5]=new HuffmaNode("F",5);
// 创建一颗哈弗曼树
huffmantree.root = huffmantree.create(nodeArray);
// 对哈弗曼树进行编码,其实可以在生成哈弗曼树的时候,一起生成哈弗曼编码。
encode(huffmantree.root);
// 按先序的方式输出哈弗曼树的每个节点的信息。
print(huffmantree.root);
}
public static HuffmaNode create(HuffmaNode[] nodeArray) {
// 表示当前要排序的起始位置
int num = 0;
// 不断循环,一直到节点集只有一个节点。
while(num<nodeArray.length-1) {
// 对当前节点集进行排序,使用了最简单的选择排序。
// 可以使用高效的排序方法,快排,归排都可以。
for(int i=num;i<nodeArray.length;i++) {
int min=i;
for(int j=i+1;j<nodeArray.length;j++) {
if(nodeArray[j].value<nodeArray[min].value) {
min=j;
}
}
swap(nodeArray,i,min);
}
// 创建新节点,记录新节点的权重
int newNodeValue = nodeArray[num].value+nodeArray[num+1].value;
HuffmaNode newNode = new HuffmaNode("分支节点",newNodeValue,nodeArray[num],nodeArray[num+1]);
// 将节点加入到节点集中,这里的num表示的起始位置,已经实现了在节点集数组中删除两个节点。
nodeArray[++num] = newNode;
}
return nodeArray[num];
}
private static void swap(HuffmaNode[] nodeArray, int i, int min) {
HuffmaNode temp = nodeArray[i];
nodeArray[i] = nodeArray[min];
nodeArray[min] = temp;
}
public static void encode(HuffmaNode node) {
encode(node,"0","1","");
}
// 对哈弗曼树中叶子节点进行编码。
public static void encode(HuffmaNode node,String a,String b,String c) {
if(node.leftChild != null) {
String temp = c+"0";
encode(node.leftChild,"0","1",temp);
}
if(node.rightChild != null) {
String temp = c+"1";
encode(node.rightChild,"0","1",temp);
}
if(node.leftChild==null && node.rightChild==null) {
node.encode=c;
}
}
// 按先序的方式输出哈弗曼树的每个节点的信息。
public static void print(HuffmaNode node) {
if(node != null) {
System.out.println(node);
print(node.leftChild);
print(node.rightChild);
}
}
}
显示结果
以上是关于Java---Huffman树的实现的主要内容,如果未能解决你的问题,请参考以下文章
深夜爆肝:万字长文3种语言实现Huffman树(强烈建议三连)