Java实现-Huffman编码与解码

Java实现-Huffman编码与解码_第1张图片

编码


  • 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 forest;
    public Map 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();
        this.root = null;
        this.codeMap = new HashMap();
    }

    /**
     * 
     * @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 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 road = new ArrayList();
        Encode(this.root, road);
    }
    private String Arr2Str(ArrayList 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 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

你可能感兴趣的:(数据结构与算法,java,编程)