参考博客:https://blog.csdn.net/qq_33366446/article/details/70251518
哈夫曼树:每次取出数组中两个值最小的节点(利用最小堆)合并成一棵树,根节点的值为两各节点的值的和,然后把根节点塞回堆中,再取出两个值最小的节点合并(左节点小于等于右节点),不断循环直到所有节点合成一棵树。
这棵树每个叶节点到根节点的距离乘其权重的积的和最小。
如果让把往左的节点编码+“0”,往右的+“1”就可以得到哈夫曼编码
import java.util.*;
public class test {
public static void main(String[] args) {
//测试
int[] a = {1,2,3,4,5,6};
HuffmanTree test = new HuffmanTree(a);
test.preOrder();
System.out.println();
test.printHuffmanCode();
}
}
//哈夫曼树类
class HuffmanTree {
Node root = null;
//节点类
class Node implements Comparable<Node> {
private int data = 0;
private Node leftChild = null;
private Node rightChild = null;
public Node(int data) {
this.data = data;
}
public Node(int data, Node leftChild, Node rightChild) {
this.data = data;
this.leftChild = leftChild;
this.rightChild = rightChild;
}
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
public Node getLeftChild() {
return leftChild;
}
public void setLeftChild(Node leftChild) {
this.leftChild = leftChild;
}
public Node getRightChild() {
return rightChild;
}
public void setRightChild(Node rightChild) {
this.rightChild = rightChild;
}
@Override
public int compareTo(Node other) {
// TODO Auto-generated method stub
return this.getData() - other.getData();
}
}
public HuffmanTree (int[] weight) { //weight是权重
buildHuffmanTree(weight);
}
/**
* 构建哈夫曼树:将输入数组转化为节点数组再导入小根堆,再导出(取出两个,合并data再放回)
*/
public void buildHuffmanTree(int[] weight) {
PriorityQueue<Node> priorityQueue = new PriorityQueue<Node>();
int weightLength = weight.length;
Node[] nodes = new Node[weightLength];
for (int i = 0; i < weightLength; i++) {
nodes[i] = new Node(weight[i]);
priorityQueue.add(nodes[i]);
}
Node temporary1 = null;
Node temporary2 = null;
Node together = null;
for (int i = 0; i < weightLength-1; i++) {//取两放一等于每次取一个,最后一个另外处理所以要减一
temporary1 = priorityQueue.poll();
temporary2 = priorityQueue.poll();
together = new Node(temporary1.getData() + temporary2.getData(), temporary1, temporary2);
priorityQueue.add(together);
}
root = priorityQueue.poll();
}
/**
* 前序遍历
*/
public void preOrder() {
if (root != null) {
preOrderDetail(root);
}
}
public void preOrderDetail(Node node) {
if (node != null) {
System.out.print(node.data);
System.out.print(" ");
preOrderDetail(node.leftChild);
preOrderDetail(node.rightChild);
}
}
public void printHuffmanCode() {
printHuffmanCodeDetail(root, "");
}
/**
* 输出哈夫曼编码
*/
public static void printHuffmanCodeDetail(Node node, String huffmanCode) {
if (node.getLeftChild() == null && node.getRightChild() == null) {
System.out.println("权值为" + node.getData() + "的结点的编码为:" + huffmanCode);
}
//如果不是叶节点则继续往下遍历
if (node.getLeftChild() != null) {
printHuffmanCodeDetail(node.getLeftChild(), huffmanCode + "0");
}
if (node.getRightChild() != null) {
printHuffmanCodeDetail(node.getRightChild(), huffmanCode + "1");
}
}
}