【说明】:核心思想在于哈夫曼树的构建、哈夫曼编码的输出、结点的定义(我个人将测试单独放在一个类中,这样主方法更加的轻捷,建议这样使用)。同时将将类放在一个包中。如下:
1.TreeNode.java(树的结点定义)
package com.yang.huffman;
/**
* 哈夫曼树结点定义
*/
public class TreeNode {
// 数据域
private String data;
// 权重
private int weight;
// 左孩子树
private TreeNode left;
// 右孩子树
private TreeNode right;
public TreeNode(String data, int weight) {
this.data = data;
this.weight = weight;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public TreeNode getLeft() {
return left;
}
public void setLeft(TreeNode left) {
this.left = left;
}
public TreeNode getRight() {
return right;
}
public void setRight(TreeNode right) {
this.right = right;
}
@Override
public String toString() {
return "TreeNode{" +
"data='" + data + '\'' +
", weight=" + weight +
", left=" + left +
", right=" + right +
'}';
}
}
2.HuffManTree.java(哈夫曼树的构建)
package com.yang.huffman;
import java.util.Collections;
import java.util.List;
/**
* 哈夫曼树的构建
*/
public class HuffManTree {
/**
* 哈夫曼树的构建方法
* @param treeNodes:存放结点的List集合
* @return 哈夫曼树构建完成的根节点
*/
public static TreeNode buildHuffManTree(List<TreeNode> treeNodes){
// 判断树是否为空
if (treeNodes.size()==0){
return null;
}
// 循环构建树,先将所有的结点排序,然后利用贪心法构建,最后返回跟结点
while (treeNodes.size()>1){
// 将结点逆序排序
reverse(treeNodes);
// 构建左节点
TreeNode left=treeNodes.get(treeNodes.size()-1);
// 构建右结点
TreeNode right=treeNodes.get(treeNodes.size()-2);
// 得出前面两个结点的父亲结点
TreeNode parent=new TreeNode(null,left.getWeight()+right.getWeight());
parent.setLeft(left);
parent.setRight(right);
// 删除List集合中的用过的两个结点
treeNodes.remove(left);
treeNodes.remove(right);
// 将生成的父亲结点放入到List集合中去
treeNodes.add(parent);
}
for (TreeNode treeNode:treeNodes){
System.out.println(treeNode);
}
return treeNodes.get(0);
}
/**
* 对List集合中结点,按照权值的大小排序(逆序)
*/
public static void reverse(List<TreeNode> treeNodes){
int n=treeNodes.size();
for(int i=n-1;i>0;i--){
for(int j=0;j<=i-1;j++){
if(treeNodes.get(j).getWeight()<=treeNodes.get(j+1).getWeight()){
TreeNode temp=treeNodes.get(j);
treeNodes.set(j,treeNodes.get(j+1));
treeNodes.set(j+1,temp);
}
}
}
}
}
3.HuffManCode.java(哈夫曼编码的得到)
package com.yang.huffman;
/**
* 得到叶子结点的哈夫曼编码:由于在定义结点的时候加入了一个code的成员变量,记录了每一个结点的一个编码(0或者1)
* 只要遍历哈夫曼树,得到每一个结点的对应的那个字符,然后拼接起来及可以得到叶子结点的编码
*/
public class HuffManCode {
/**
* 先序遍哈夫曼树得到叶子结点的哈夫曼编码
* @param rootNode:根节点
*/
public static void getHuffManCode(TreeNode rootNode,String huffManCode){
if (rootNode.getData()!=null){
System.out.print("数据:"+rootNode.getData()+" "+"哈夫曼编码:"+huffManCode);
System.out.println();
return;
}
getHuffManCode(rootNode.getLeft(),huffManCode+"0");
getHuffManCode(rootNode.getRight(),huffManCode+"1");
return;
}
}
4.HuffManTest.java(测试)
package com.yang.huffman;
import com.yang.traverse.BinaryTree;
import java.util.ArrayList;
import java.util.List;
/**
* 哈夫曼树的测试
*/
public class HuffManTest {
public static void main(String[] args) {
List<TreeNode> treeNodes=new ArrayList<TreeNode>();
treeNodes.add(new TreeNode("A",3));
treeNodes.add(new TreeNode("B",1));
treeNodes.add(new TreeNode("C",6));
treeNodes.add(new TreeNode("D",4));
TreeNode root=HuffManTree.buildHuffManTree(treeNodes);
HuffManCode.getHuffManCode(root,"");
}
}
【结果】: