import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class HuffmanTree<T> {
private HuffmanTreeArrayNode<T>[] huffmanTree;
public void createHuffmanTree(List<HuffmanTreeArrayNode<T>> leafNodes){//创建基于顺序存储的Huffman树
int leafCount = leafNodes.size();
huffmanTree = new HuffmanTreeArrayNode[2*leafCount-1];
int treeIndex = 0;
for (HuffmanTreeArrayNode<T> node: leafNodes) {
huffmanTree[treeIndex++] = node;
}
for (int i = leafCount; i < huffmanTree.length; i++) {
double min1 , min2;
min1 = min2 = Double.MAX_VALUE;
int min1Index , min2Index;
min1Index = min2Index = 0;
for (int j = 0; j < leafCount; j++) {
if (huffmanTree[j].getParent()==-1){
if (huffmanTree[j].getWeight()<min1){
min2 = min1;
min2Index = min1Index;
min1 = huffmanTree[j].getWeight();
min1Index = j;
}else if (huffmanTree[j].getWeight()<min2){
min2 = huffmanTree[j].getWeight();
min2Index = j;
}
}
}
huffmanTree[min1Index].setParent(leafCount);
huffmanTree[min2Index].setParent(leafCount);
huffmanTree[i] = new HuffmanTreeArrayNode<>(min1+min2);
huffmanTree[i].setLeftChild(min1Index);
huffmanTree[i].setLeftChild(min2Index);
}
}
public Map<T,String> buildHuffmanCodes(){//基于Huffman树的Huffman编码
int leafCount = (huffmanTree.length+1)/2;
Map<T,String> codes = new HashMap<>();
for (int i = 0; i < leafCount; i++) {
String code = "";
int parentIndex = huffmanTree[i].getParent();
while (parentIndex!=-1){
if (i == huffmanTree[parentIndex].getLeftChild()){
code = 0 + code;
}else {
code = 1 + code;
}
parentIndex = huffmanTree[parentIndex].getParent();
}
codes.put(huffmanTree[i].getData(),code);
}
return codes;
}
}
class HuffmanTreeArrayNode<T>{
private T data;
private double weight;
private int leftChild = -1;
private int rightChild = -1;
private int parent = -1;
public HuffmanTreeArrayNode(double weight) {
this.weight = weight;
}
public HuffmanTreeArrayNode(T data, double weight) {
this.data = data;
this.weight = weight;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
public int getLeftChild() {
return leftChild;
}
public void setLeftChild(int leftChild) {
this.leftChild = leftChild;
}
public int getRightChild() {
return rightChild;
}
public void setRightChild(int rightChild) {
this.rightChild = rightChild;
}
public int getParent() {
return parent;
}
public void setParent(int parent) {
this.parent = parent;
}
}