作为一个菜鸟(大学混子)前几天听到Huffman 编码,突然感觉这个名字好熟悉,然后搜了一下定义,就想着自己实现一个玩玩,不多说,直接上代码:
先定义节点对象,一个内部类:
public static class HTNode<E> {
/**
* 左子节点
*/
private HTNode left;
/**
* 右子节点
*/
private HTNode right;
/**
* 权重
*/
private int power;
/**
* 对应的字符
*/
private E v;
public HTNode(int power){
this.setPower(power);
}
public HTNode(){
}
public HTNode(int power, E v){
this.power = power;
this.v = v;
}
public HTNode getLeft() {
return left;
}
public void setLeft(HTNode left) {
this.left = left;
}
public HTNode getRight() {
return right;
}
public void setRight(HTNode right) {
this.right = right;
}
public int getPower() {
return power;
}
public void setPower(int power) {
this.power = power;
}
public E getV() {
return v;
}
public void setV(E v) {
this.v = v;
}
/**
* 前序遍历函数
* @param node
*/
public void printfVLR(HTNode node){
if(node == null){
return;
}
System.out.println(node.power+" "+node.v);
//遍历左子树
printfVLR(node.left);
//遍历右子树
printfVLR(node.right);
}
}
接下来是构建Huffman tree的相关函数:
public class TestHuffmanTree {
public static void main(String[] args) {
int[] arr = {6, 5, 3, 2, 3, 8, 9, 7, 1, 1, 9};
//构建huffman tree
root = huffmanTree(arr);
//前序遍历
root.printfVLR(root);
}
private static HTNode root;
/**
* 先把数组构建成一个一个节点,对节点集合进行排序
* 移除两个最小的值组成新的节点,并把新节点插入集合,
* 再对集合进行排序,重复上面的操作,直到集合仅存一个节点
* @param arr
* @return
*/
public static HTNode huffmanTree(int[] arr){
if(null == arr || arr.length == 0)
return null;
HTNode[] htNodes = transfer(arr);
return huffmanTree(htNodes);
}
private static HTNode huffmanTree(HTNode[] arr){
long start = System.nanoTime();
if(null == arr || arr.length == 0)
return null;
while(arr.length > 1){
for(int i=0;i< arr.length;++i){
if(arr.length >= 2){
QuickSort.quickSortT(arr, 0, arr.length-1);
}
//取出两个节点,结合成新节点,
HTNode n1 = arr[0];
HTNode n2 = arr[1];
HTNode newNode = new HTNode(n1.power+ n2.power);
newNode.setLeft(n1);
newNode.setRight(n2);
arr = Arrays.copyOfRange(arr, 1, arr.length);
arr[0] = newNode;
}
}
root = arr[0];
System.out.println("耗时:"+(System.nanoTime() - start));
return root;
}
private static HTNode[] transfer(int[] arr){
HTNode[] htNodes = new HTNode[arr.length];
for(int i=0;i<arr.length;++i){
htNodes[i] = new HTNode(arr[i]);
}
return htNodes;
}
public static <E> HTNode<E> getHuffmanTree(Map<E, Integer> map){
return huffmanTree(transfer(map));
}
public static <E> HTNode[] transfer(Map<E, Integer> map){
HTNode[] htNodes = new HTNode[map.size()];
int i=0;
Iterator<Map.Entry<E, Integer>> iterator = map.entrySet().iterator();
while(iterator.hasNext()){
Map.Entry<E, Integer> next = iterator.next();
htNodes[i] = new HTNode(next.getValue(), next.getKey());
i++;
}
return htNodes;
}
}
接下是排序代码,这里我用的是快排:
public class QuickSort {
public static <T extends TestHuffmanTree.HTNode> void quickSortT(T[] arr, int start, int end){
if(start >= end)
return;
int midIdx = subQuickSort(arr, start, end);
quickSortT(arr, 0, midIdx -1);
quickSortT(arr, midIdx+1, end);
}
public static <T extends TestHuffmanTree.HTNode> int subQuickSort(T[] arr, int start, int end){
T mid = arr[start];
while (start < end){
if(arr[end].getPower() >= mid.getPower() && start < end){
end--;
}
arr[start] = arr[end];
while(arr[start].getPower() <= mid.getPower() && start < end){
start++;
}
arr[end] = arr[start];
}
arr[start] = mid;
return start;
}
}
完事儿!