哈夫曼編碼測試

哈夫曼編碼實踐

實踐要求

  • 設有字符集:S={a,b,c,d,e,f,g,h,i,j,k,l,m,n.o.p.q,r,s,t,u,v,w,x,y,z}。
    給定一個包含26個英文字母的文件,統計每一個字符出現的機率,根據計算的機率構造一顆哈夫曼樹。
    並完成對英文文件的編碼和解碼。
  • 要求:
    (1)準備一個包含26個英文字母的英文文件(能夠不包含標點符號等),統計各個字符的機率
    (2)構造哈夫曼樹
    (3)對英文文件進行編碼,輸出一個編碼後的文件
    (4)對編碼文件進行解碼,輸出一個解碼後的文件

哈夫曼編碼

  • 一種編碼方式,能夠經過其算法來減少數據的存儲空間,從而達到壓縮文件的目的。
  • 主要原理:
    • 計算各個元素出現的頻率也就是每一個元素所佔總元素的權重。根據權重的大小來進行後續的處理。
    • 哈夫曼樹,經過樹的數據結構來存儲數據。哈夫曼樹能夠不爲徹底樹,其度爲2。特色在於,父結點老是給左子樹爲0,右子樹爲1。
    • 哈夫曼樹的構造。對於全部元素,首先求出其全部的權重。對於這些森林,每次選出權重最小的兩棵樹,求其和,做爲這兩棵樹的父結點。最終構造出哈夫曼樹。根據其構造方法,咱們能夠發現,權重越大的結點,也就是其對應的元素越靠上,這樣作的緣由是由於權重越大,出現的越發頻繁,因此,以較短長度來替換出現次數最多的元素。從而使得存儲空間得以減小。
    • 廣度優先遍歷,在獲得各個結點的編碼時,咱們使用廣度優先遍從來根據每層來增長一個0或1。不過,哈夫曼樹是個樹,也就是使用層序遍從來獲得每一個結點的編碼。

代碼實現

  • 在將對一個個的字符轉換時,我想到計算機中每一個元素都對應着一個ASCII碼錶值,因此,將其轉化爲ASCII值後,統計將變得較爲便利。同時,爲了存儲數據方便,我使用了線性表來存儲每個結點。
  • 廣度優先遍歷,以前學習過這種遍歷方法,也就是使用隊列和列表來獲得相應的結點,並在此時得出對應的哈夫曼碼。先將父結點存入隊列,再將其孩子結點存入隊列,再將其彈出,彈出的進入列表。這樣,這個列表就存儲着全部的帶着霍夫曼碼的結點。
public Node createTreee(List<Node> nodes){

        while (nodes.size()>1){
            Collections.sort(nodes);
            Node left = nodes.get(nodes.size()-1);
            Node right = nodes.get(nodes.size()-2);
            Node parent = new Node(null,left.getWeight()+right.getWeight());
            parent.setLeft(left);
            parent.setRight(right);
            nodes.remove(nodes.size()-1);
            nodes.remove(nodes.size()-1);
            nodes.add(parent);

        }
        return nodes.get(0);
    }

    //廣度遍歷
    public  static List<Node> levelTraverse(Node root){
        List<Node> list = new ArrayList<Node>();
        Queue<Node> queue = new ArrayDeque<Node>();

        if (root != null) {
            queue.offer(root);
            root.getLeft().setCode(root.getCode() + "0");
            root.getRight().setCode(root.getCode() + "1");
        }

        while (!queue.isEmpty()) {
            list.add(queue.peek());
            Node node = queue.poll();
            if (node.getLeft() != null)
                node.getLeft().setCode(node.getCode() + "0");
            if (node.getRight() != null)
                node.getRight().setCode(node.getCode() + "1");

            if (node.getLeft() != null) {
                queue.offer(node.getLeft());
            }

            if (node.getRight() != null) {
                queue.offer(node.getRight());
            }
        }
        return list;
    }

結點實現類node

public Node(T data,double weight){
        this.data = data;
        this.weight = weight;
        this.code="";
    }

    public Node(T data, double weight, String code){
        this.data = data;
        this.weight = weight;
        this.code = code;

    }

運行結果



出現的問題

  • 出現了比較多的問題有類轉化問題。
  • 由於使用了ASCII值,因此在使用諸如Long.parseLong()方法時,就會出現錯誤,由於char值不能使用String值進行強制類型轉化,因此,在獲得一個char值後,若是咱們想使其變爲String型時,最簡單的方法就是給它加一個空字符串也就是「」,就能夠了。
  • 同時,此次在讀取文本時也出現了問題。每每最後一位的空格可能致使出錯,由於其不可見,咱們每每可能忽視這一細節。在寫入時也可能致使出現這種錯誤。
相關文章
相關標籤/搜索