參考博客: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");
}
}
}