哈夫曼编码译码java实现

针对只含有数字,字母的字符串,若有其他字符改动一下即可。
一下代码由本人手写,先写了c++再写的java(不怎么熟练java)有错欢迎交流。本人使用工具idea, jdk版本为11
转载请注明出处。

c++版

Main.class

import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Scanner;

public class Main {
    //自定义比较类
//     static Comparable<queueNode> nodeCmp = new Comparator<queueNode>() {
//
//        public int compareTo(queueNode o1, queueNode o2) {
//            //升序排序
//           return o1.weight - o2.weight;
//        }
//    };
    //创建哈夫曼树
     public static void createHuffManTree(huffManNode[] huffManTree, char[] chars, int n, int[] cnt)
    {
        //小根堆
        PriorityQueue<queueNode> heap = new PriorityQueue<queueNode>(520, new Comparator<queueNode>() {
            @Override
            public int compare(queueNode o1, queueNode o2) {
                return o1.weight-o2.weight;
            }
        }
        );
        //入队
        for(int i=1; i<=n; ++i) {
            heap.add(new queueNode(cnt[chars[i]-'0'],i));
        }
        int m=n*2-1;
        //初始化哈夫曼树数组
        for(int i=1; i<=m; ++i){
            if(i<=n) huffManTree[i]= new huffManNode(cnt[chars[i]-'0'],0,0,0);
            else huffManTree[i]= new huffManNode(0,0,0,0);
        }
        //建树
        for(int i= n+1; i<= m; ++i){
            //找到最小的结点
            queueNode minNode = heap.poll();
            queueNode secondMinNode = heap.poll();
            huffManTree[minNode.index].parent = i;
            huffManTree[secondMinNode.index].parent = i;
            huffManTree[i].leftChild = minNode.index;
            huffManTree[i].rightChild = secondMinNode.index;
            huffManTree[i].weight =  minNode.weight + secondMinNode.weight;
            //新结点加入小根堆
            heap.add(new queueNode(huffManTree[i].weight,i));
        }
    }
    public  static  void huffManEnCode(huffManCode[] huffManCodes, huffManNode[] huffManTree,char[] chars,int n) {
        if(n==1) {
            huffManCodes[1] = new huffManCode(chars[1],"0");
        }
        else {
            //求n个叶子结点对应的哈夫曼编码
            for(int i=1; i<=n; i++) {
               // System.out.println("debughuffManEnCode");
                String tmpCode ="";
                int tmpIndex=2*n-1;
                for(int j = i, p = huffManTree[i].parent; p!=0; j=p, p=huffManTree[p].parent){
                    if(huffManTree[p].leftChild==j) tmpCode+='0';
                    else tmpCode+='1';
                }
                char[] chars1 = tmpCode.toCharArray();
                tmpCode="";
                for(int j=chars1.length-1; j>=0; --j) {
                    tmpCode+=chars1[j];
                }
                huffManCodes[i]= new huffManCode(chars[i],tmpCode);
            }
           // System.out.println("debughuffManEnCode");
        }
    }
    //获取输入url的 哈夫曼编码
    public  static  String getHuffManCode(char[] urlchars,huffManCode[] huffManCodes,int n) {
        String tmpCode="";
        for(int i=0; i<urlchars.length; ++i) {
            for(int j=1; j<=n; ++j) {
                if(huffManCodes[j].ch==urlchars[i]) {
                    tmpCode+=huffManCodes[j].code;
                    break;
                }
            }
        }
        return tmpCode;
    }
    //将哈夫曼编码译码
    public static  String huffManDeCode(String tmpCode, huffManCode[] huffManCodes,huffManNode[] huffManTree,int n){
         String myDecode="";
         if(n==1) {
             for(int i=0; i<tmpCode.length(); ++i) myDecode+=huffManCodes[1].code;
         }
         else{
             int tmpIndex=2*n-1;
             char[] tmpCodeChars = tmpCode.toCharArray();
             for(int i=0; i<tmpCodeChars.length; ++i){
                 if(tmpCodeChars[i]=='0') tmpIndex=huffManTree[tmpIndex].leftChild;
                 else tmpIndex=huffManTree[tmpIndex].rightChild;
                 if(huffManTree[tmpIndex].leftChild ==0 &&huffManTree[tmpIndex].rightChild==0){
                     myDecode+=huffManCodes[tmpIndex].ch;
                     tmpIndex=2*n - 1;
                 }
             }
         }
        return myDecode;
    }
    public static void main(String[] args) {
        //创建对象
        Scanner in = new Scanner(System.in);
        //读入字符串用next(), 以空格划分
        System.out.println("请输入url: ");
        String url = in.next();
        //将url转为char 数组
        char[] urlChars = url.toCharArray();
        //标记数组,判断哪些字符出现过
        boolean[] visited = new boolean[520];
        //取出url中的字符(去重后)
        char[] chars = new char[urlChars.length+5];
        //记录字符出现频次
        int [] cnt = new int[200];
        int len=0;

        for(int i=0; i<urlChars.length; ++i) {
             if(visited[urlChars[i]-'0']==false) {
                 chars[++len]=urlChars[i];
                 visited[urlChars[i]-'0']=true;
             }
             cnt[urlChars[i]-'0']++;
        }
        chars[len+1]='\0';
        System.out.println(len);
       //第一步: 建立一颗哈夫曼树
        //定义一颗哈夫曼树数组
        huffManNode[] huffManTree= new huffManNode[520];
        createHuffManTree(huffManTree, chars,len, cnt);

        //第二步: 进行哈夫曼编码
        huffManCode[] huffManCodes = new huffManCode[520];
        huffManEnCode(huffManCodes,huffManTree,chars,len);

        //第三步:获取输入url的哈夫曼编码
        String myHuffManEnCode = getHuffManCode(urlChars, huffManCodes,len);
        String myHuffManDeCode = huffManDeCode(myHuffManEnCode, huffManCodes, huffManTree, len);
        System.out.println("哈夫曼编码:"+myHuffManEnCode);
        System.out.println("哈夫曼译码:"+myHuffManDeCode);
    }

}

queueNode.class

//优先队列中的结点类型
public class queueNode  {
    public Integer weight;
    public Integer index;

    public queueNode(Integer weight, Integer index) {
        this.weight = weight;
        this.index = index;
    }
}

huffManNode.class

//此类是哈夫曼树的结点,对应c++里面的一个结构体
public class huffManNode {
    //public int parent;
    //权重
    public Integer weight;
    //父亲结点
    public Integer parent;
    //左儿子结点
    public Integer leftChild;
    //右儿子结点
    public Integer rightChild;

    public huffManNode(Integer weight, Integer parent, Integer leftChild, Integer rightChild) {
        this.weight = weight;
        this.parent = parent;
        this.leftChild = leftChild;
        this.rightChild = rightChild;
    }
}

huffManCode.class

//此类存储每个字符对应的编码
public class huffManCode {
    //ch代表对应的字符
    public char ch;
    //code代表ch对应字符的编码
    public String  code;

    public huffManCode(char ch, String code) {
        this.ch = ch;
        this.code = code;
    }
}

目录结构

在这里插入图片描述

posted @ 2022-08-28 08:43  翔村亲亲鸟  阅读(137)  评论(0编辑  收藏  举报