最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

如何用Java實(shí)現(xiàn)啥夫曼編碼

 更新時(shí)間:2013年08月14日 10:25:10   作者:  
在開(kāi)發(fā)手機(jī)程序時(shí),總是希望壓縮網(wǎng)絡(luò)傳輸?shù)男畔?,以減少流量。本文僅以哈夫曼編碼為引導(dǎo),拋磚引玉,實(shí)現(xiàn)壓縮功能

大家可能會(huì)想,程序和第三方提供了很多壓縮方式,何必自己寫(xiě)壓縮代碼呢?不錯(cuò),如GZIP這樣的壓縮工具很多,可是在某些情況下(如文本內(nèi)容小且字符不重復(fù)),GZIP壓縮后會(huì)比原始文本還要大。所以在某些特殊情況下用自己的壓縮方式可以更優(yōu)。

大家可能早已忘記了在學(xué)校學(xué)習(xí)的哈夫曼知識(shí),可以先在百度百科了解一下哈夫曼知識(shí):http://baike.baidu.com/view/127820.htm

哈夫曼思想:統(tǒng)計(jì)文本字符重復(fù)率,求出各字符權(quán)值,再構(gòu)造出一顆最優(yōu)二叉樹(shù)(又稱哈夫曼樹(shù)),然后給每個(gè)葉子結(jié)點(diǎn)生成一個(gè)以位(bit)為單位的碼值,每個(gè)碼值不能做為其 他碼值的前綴,再將碼值合并以每8個(gè)生成一個(gè)字節(jié)。

復(fù)制代碼 代碼如下:

package com.huffman;

/**
 * 結(jié)點(diǎn)
 * @author Davee
 */
public class Node implements Comparable<Node> {
    int weight;//權(quán)值
    Node leftChild;//左孩子結(jié)點(diǎn)
    Node rightChild;//右孩子結(jié)點(diǎn)
    String huffCode;
    private boolean isLeaf;//是否是葉子
    Character value;

    public Node(Character value, int weight) {
        this.value = value;
        this.weight = weight;
        this.isLeaf = true;
    }

    public Node(int weight, Node leftChild, Node rightChild) {
        this.weight = weight;
        this.leftChild = leftChild;
        this.rightChild = rightChild;
    }

    public void increaseWeight(int i) {
        weight += i;
    }

    public boolean isLeaf() {
        return isLeaf;
    }

    @Override
    public int compareTo(Node o) {
        return this.weight - o.weight;
    }
}


復(fù)制代碼 代碼如下:

package com.huffman;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

public class HuffmanTree {
    private boolean debug = false;

    private HashMap<Character, Node> nodeMap;
    private ArrayList<Node> nodeList;

    public HuffmanTree() {
        nodeMap = new HashMap<Character, Node>();
        nodeList = new ArrayList<Node>();
    }

    public void setDebug(boolean debug) {
        this.debug = debug;
    }

    public String decode(Map<String, Character> codeTable, String binary) {
        int begin = 0, end = 1, count = binary.length();
        StringBuffer sb = new StringBuffer();
        while (end <= count) {
            String key = binary.substring(begin, end);
            if (codeTable.containsKey(key)) {
                sb.append(codeTable.get(key));
                begin = end;
            } else {
            }
            end++;
        }
        return sb.toString();
    }

    public String encode(String originText) {
        if (originText == null) return null;

        calculateWeight(originText);

//        if (debug) printNodes(nodeList);

        Node root = generateHuffmanTree(nodeList);

        generateHuffmanCode(root, "");

        if (debug) printNodes(root);

        StringBuffer sb = new StringBuffer();
        for (Character key : originText.toCharArray()) {
            sb.append(nodeMap.get(key).huffCode);
        }
        if (debug) System.out.println("二進(jìn)制:"+sb.toString());

        return sb.toString();
    }

    /**
     * 計(jì)算葉子權(quán)值
     * @param text
     */
    private void calculateWeight(String text) {
        for (Character c : text.toCharArray()) {
            if (nodeMap.containsKey(c)) {
                nodeMap.get(c).increaseWeight(1);//權(quán)值加1
            } else {
                Node leafNode = new Node(c, 1);
                nodeList.add(leafNode);
                nodeMap.put(c, leafNode);
            }
        }
    }

    /**
     * 生成哈夫曼樹(shù)
     * @param nodes
     */
    private Node generateHuffmanTree(ArrayList<Node> nodes) {
        Collections.sort(nodes);
        while(nodes.size() > 1) {
            Node ln = nodes.remove(0);
            Node rn = nodes.remove(0);
            insertSort(nodes, new Node(ln.weight + rn.weight, ln, rn));
        }
        Node root = nodes.remove(0);
        nodes = null;
        return root;
    }

    /**
     * 插入排序
     * @param sortedNodes
     * @param node
     */
    private void insertSort(ArrayList<Node> sortedNodes, Node node) {
        if (sortedNodes == null) return;

        int weight = node.weight;
        int min = 0, max = sortedNodes.size();
        int index;
        if (sortedNodes.size() == 0) {
            index = 0;
        } else if (weight < sortedNodes.get(min).weight) {
            index = min;//插入到第一個(gè)
        } else if (weight >= sortedNodes.get(max-1).weight) {
            index = max;//插入到最后
        } else {
            index = max/2;
            for (int i=0, count=max/2; i<=count; i++) {
                if (weight >= sortedNodes.get(index-1).weight && weight < sortedNodes.get(index).weight) {
                    break;
                } else if (weight < sortedNodes.get(index).weight) {
                    max = index;
                } else {
                    min = index;
                }
                index = (max + min)/2;
            }
        }
        sortedNodes.add(index, node);
    }

    private void generateHuffmanCode(Node node, String code) {
        if (node.isLeaf()) node.huffCode = code;
        else {
            generateHuffmanCode(node.leftChild, code + "0");
            generateHuffmanCode(node.rightChild, code + "1");
        }
    }

    /**
     * 生成碼表
     * @return
     */
    public Map<String, Character> getCodeTable() {
        Map<String, Character> map = new HashMap<String, Character>();
        for (Node node : nodeMap.values()) {
            map.put(node.huffCode, node.value);
        }
        return map;
    }

    /**
     * 打印節(jié)點(diǎn)信息
     * @param root
     */
    private void printNodes(Node root) {
        System.out.println("字符  權(quán)值  哈夫碼");
        printTree(root);
    }

    private void printTree(Node root) {
        if (root.isLeaf()) System.out.println((root.value == null ? "   " : root.value)+"    "+root.weight+"    "+(root.huffCode == null ? "" : root.huffCode));
        if (root.leftChild != null) printTree(root.leftChild);
        if (root.rightChild != null) printTree(root.rightChild);
    }

    /**
     * 打印節(jié)點(diǎn)信息
     * @param nodes
     */
    private void printNodes(ArrayList<Node> nodes) {
        System.out.println("字符  權(quán)值  哈夫碼");
        for (Node node : nodes) {
            System.out.println(node.value+"    "+node.weight+"    "+node.huffCode);
        }
    }
}


復(fù)制代碼 代碼如下:

package com.test;

import java.util.Map;

import com.huffman.HuffUtils;
import com.huffman.HuffmanTree;

public class Test {
    public static void main(String[] args) {
        String originText = "abcdacaha";
        HuffmanTree huffmanTree = new HuffmanTree();
        huffmanTree.setDebug(true);//測(cè)試
        String binary = huffmanTree.encode(originText);
        byte[] bytes = HuffUtils.binary2Bytes(binary);
        Map<String, Character> codeTable = huffmanTree.getCodeTable();
        int lastByteNum = binary.length() % 8;
        System.out.println(bytes.length);
        //將bytes、codeTable、 lastByteNum傳遞到服務(wù)器端
        //省略。。。。。。

        /*
                         服務(wù)器端解析
                         接收到參數(shù),并轉(zhuǎn)換成bytes、relationMap、 lastByteNum
        */
        String fullBinary = HuffUtils.bytes2Binary(bytes, lastByteNum);
        System.out.println("服務(wù)器二進(jìn)制:"+fullBinary);
        String retrieveText = huffmanTree.decode(codeTable, fullBinary);
        System.out.println("恢復(fù)文本:"+retrieveText);
    }
}

相關(guān)文章

  • Spring-全面詳解(學(xué)習(xí)總結(jié))

    Spring-全面詳解(學(xué)習(xí)總結(jié))

    這篇文章主要介紹了詳解Spring框架入門(mén),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧,希望能給你帶來(lái)幫助
    2021-07-07
  • JVM 心得 OOM時(shí)的堆信息獲取方法與分析

    JVM 心得 OOM時(shí)的堆信息獲取方法與分析

    下面小編就為大家?guī)?lái)一篇JVM 心得 OOM時(shí)的堆信息獲取方法與分析。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-10-10
  • 淺談java中的局部變量和全局變量

    淺談java中的局部變量和全局變量

    這篇文章主要涉及了java中的局部變量和全局變量,就二者的含義、生存時(shí)間和創(chuàng)建位置作了介紹,需要的朋友可以參考下。
    2017-09-09
  • 如何使用IDEA從SVN服務(wù)端檢出項(xiàng)目

    如何使用IDEA從SVN服務(wù)端檢出項(xiàng)目

    這篇文章主要介紹了如何使用IDEA從SVN服務(wù)端檢出項(xiàng)目問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • java 操作gis geometry類型數(shù)據(jù)方式

    java 操作gis geometry類型數(shù)據(jù)方式

    這篇文章主要介紹了java 操作gis geometry類型數(shù)據(jù)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • Java編程幾個(gè)循環(huán)實(shí)例代碼分享

    Java編程幾個(gè)循環(huán)實(shí)例代碼分享

    這篇文章主要介紹了Java編程幾個(gè)循環(huán)實(shí)例代碼分享,多看多練,小編覺(jué)得還是挺不錯(cuò)的,這里分享給大家,供需要的朋友參考。
    2017-10-10
  • 詳解Java如何向http/https接口發(fā)出請(qǐng)求

    詳解Java如何向http/https接口發(fā)出請(qǐng)求

    這篇文章主要為大家詳細(xì)介紹了Java如何實(shí)現(xiàn)向http/https接口發(fā)出請(qǐng)求,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-01-01
  • 淺談Java中static關(guān)鍵字的作用

    淺談Java中static關(guān)鍵字的作用

    這篇文章主要介紹了Java中static關(guān)鍵字的作用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • JAVA如何獲取工程下的文件

    JAVA如何獲取工程下的文件

    這篇文章主要介紹了JAVA如何獲取工程下的文件,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-08-08
  • Java通過(guò)XPath獲取XML文件中符合特定條件的節(jié)點(diǎn)

    Java通過(guò)XPath獲取XML文件中符合特定條件的節(jié)點(diǎn)

    今天小編就為大家分享一篇關(guān)于Java通過(guò)XPath獲取XML文件中符合特定條件的節(jié)點(diǎn),小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-01-01

最新評(píng)論

蓝山县| 景德镇市| 洮南市| 汾西县| 瑞安市| 华坪县| 织金县| 衢州市| 通海县| 井陉县| 乌海市| 余姚市| 江西省| 多伦县| 津南区| 寿光市| 呼伦贝尔市| 高平市| 台安县| 广灵县| 康马县| 江门市| 临沂市| 塔河县| 太保市| 长岭县| 维西| 搜索| 营山县| 江西省| 永平县| 潜江市| 天祝| 青河县| 成安县| 永平县| 垦利县| 灌云县| 珠海市| 古浪县| 宁明县|