编码
- 1 从森林中选取2颗子树进行合并,将生成的新树重新插入森林
- 2 重复1,直到森林中只有一棵树
所有的待编码节点成为了这棵树的叶子结点,频度越高越靠近树根
解码
- 同样采用树形结构进行解码(所有叶子存储数据,路径即编码)
如果码值是0则向左子树寻找;是1则向右子树寻找,直到找到叶子结点
- Code ->
package src;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
*
* @author Henry
* @desc Huffman Code
*
*/
/**
* Result
*/
class Result {
public BTNode minFirst;
public int minFirstIndex;
public BTNode minSecond;
public int minSecondIndex;
public Result(BTNode f, int fi, BTNode s, int si) {
this.minFirst = f;
this.minSecond = s;
this.minFirstIndex = fi;
this.minSecondIndex = si;
}
}
/**
*
* @author Henry
*
* @desc Huffman Oprations
*/
class Huffman {
public int [] sourceSet;
public ArrayList<BTNode> forest;
public Map<BTNode, String> codeMap;
public BTNode root;
public static final int DELETE_FLAG = Integer.MAX_VALUE;
public static final int FOREST_SUCCESS = 1;
public Huffman(int [] arr) {
this.sourceSet = arr;
this.forest = new ArrayList<BTNode>();
this.root = null;
this.codeMap = new HashMap<BTNode, String>();
}
/**
*
* @param arr
* @return firstMinNum and secondMinMum of arr
*
*/
private Result SearchMinFirstAndSecond() {
BTNode fmin = new BTNode(Integer.MAX_VALUE);
BTNode smin = new BTNode(Integer.MAX_VALUE);
int fi = 0;
int si = 0;
Iterator<BTNode> it = this.forest.iterator();
BTNode n;
int i = 0;
while (i < this.forest.size())
{
n = it.next();
if (n.data < fmin.data) {
smin = fmin;
fmin = n;
si = fi;
fi = i;
} else if (n.data < smin.data) {
smin = n;
si = i;
}
i++;
}
Result r = new Result(fmin, fi, smin, si);
// System.out.println(fmin.data+"*|index:"+fi+"|"+smin.data+"*|index:"+si);
return r;
}
/**
* init a forest
*/
private void InitForest() {
BTNode node;
for (int i = 0; i < this.sourceSet.length; i++) {
node = new BTNode(this.sourceSet[i]);
this.forest.add(node);
}
}
public void CreateHuffmanTree() {
/** init a forest by sourceSet */
this.InitForest();
while (this.forest.size() != FOREST_SUCCESS) {
// Log(this.forest.size());
// get 2 min elements
Result res = this.SearchMinFirstAndSecond();
// build tree
BTNode leftNode = res.minFirst;
BTNode rightNode = res.minSecond;
BTNode root = new BTNode(leftNode.data+rightNode.data);
root.left = leftNode;
root.right = rightNode;
// insert tree into forest
this.forest.add(root);
// remove 2min elements already found
this.forest.remove(res.minFirst);
this.forest.remove(res.minSecond);
}
this.root = this.forest.get(0);
}
/**
* Put huffman code of b-tree
*/
public void HuffmanEncode() {
ArrayList<Integer> road = new ArrayList<Integer>();
Encode(this.root, road);
}
private String Arr2Str(ArrayList<Integer> arr)
{
String str = new String();
for (int i = 0; i < arr.size(); i++) {
str += (arr.get(i));
}
return str;
}
private void Encode(BTNode root, ArrayList<Integer> road) {
if (root != null) {
// road.add(root.data); // print path
if (root.left == null && root.right == null) {
// map the code
this.codeMap.put(root, Arr2Str(road));
for (int i = 0; i < road.size(); i++) {
System.out.print(road.get(i)+" | ");
}
System.out.println(" LEAF: { "+root.data+" }");
//road.remove(road.size()-1);
} else {
road.add(0);
Encode(root.left, road);
road.add(1);
Encode(root.right, road);
}
if (road.size() >= 1) {
road.remove(road.size()-1); // remove path that has been through
}
}
}
/**
*
* @param code: huffmen code
*/
private int DecodeRecursive(BTNode root, char []arr, int currentIndex) {
int flag = 0;
if (root.left == null && root.right == null) {
// find the node
System.out.print("---------------------------\ncode is: "+this.codeMap.get(root));
System.out.println("\nDecode to: | "+root.data+" |");
flag = currentIndex;
} else {
if (currentIndex == arr.length) {
flag = 0;
} else {
if (arr[currentIndex] == '0') {
// left tree
flag = DecodeRecursive(root.left, arr, currentIndex+1);
} else {
// right
flag = DecodeRecursive(root.right, arr, currentIndex+1);
}
}
}
return flag;
}
public void HuffmanDecode(String code) {
char [] codeArr = code.toCharArray();
int currentIndex = 0;
int index;
while (true) {
index = DecodeRecursive(this.root, codeArr, currentIndex);
if (index != 0) {
currentIndex = index;
} else {
break;
}
}
}
}
public class HuffmanCode {
public static void main(String[] args) {
/**
* @Test: Huffman
*/
int [] arr = {5,6,11,2,9,3};
Huffman hm = new Huffman(arr);
hm.CreateHuffmanTree();
Tree t = new Tree();
System.out.println("|+++++++++++++++PreOrder+++++++++++++++++|");
t.PreOrderTraversal(hm.root);
System.out.print("\n");
hm.HuffmanEncode();
hm.HuffmanDecode("00101100110101");
}
}
- Console ->
|+++++++++++++++PreOrder+++++++++++++++++|
36 |15 |6 |9 |21 |10 |5 |5 |2 |3 |11 |
0 | 0 | LEAF: { 6 }
0 | 1 | LEAF: { 9 }
1 | 0 | 0 | LEAF: { 5 }
1 | 0 | 1 | 0 | LEAF: { 2 }
1 | 0 | 1 | 1 | LEAF: { 3 }
1 | 1 | LEAF: { 11 }
---------------------------
code is: 00
Decode to: | 6 |
---------------------------
code is: 1011
Decode to: | 3 |
---------------------------
code is: 00
Decode to: | 6 |
---------------------------
code is: 11
Decode to: | 11 |
---------------------------
code is: 01
Decode to: | 9 |
---------------------------
code is: 01
Decode to: | 9 |
END

本文介绍了一种数据压缩算法——霍夫曼编码的实现过程。包括构建霍夫曼树、编码与解码的方法。通过具体实例展示了霍夫曼编码如何减少数据存储空间。
582

被折叠的 条评论
为什么被折叠?



