哈夫曼编码原理代码

哈夫曼树─即最优二叉树,带权路径长度最小的二叉树,经常应用于数据压缩。通过将高频率字符用较短字节进行表示而不是统一表示的方法达到字符串的压缩。

啥是带权路径?- 每一个结点代表着不同的数字,而这些不同的数字称作结点的权值。

  • 二叉树中一个结点到另一个结点经过的结点方式是唯一的,这些经过的结点称作两个结点之间的路径。而由结点A到结点B中间经历的结点数目加1即为结点A到B的路径长度

哈夫曼为啥是前缀编码?

因为**定长编码已经用相同的位数这个条件保证了任一个字符的编码都不会成为其它编码的前缀,**所以这种情况只会出现在变长编码当中,要想避免这种情况,我们就必须用一个条件来制约定长编码,这个条件就是要想成为压缩编码,变长编码就必须是前缀编码.什么是前缀编码呢?所谓的前缀编码就是任何一个字符的编码都不能是另一个字符编码的前缀。假如有那扫描到前缀,就没法确定是哪个

正式代码:

package Huffman;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

public class HaffmanTree {
    public static void main(String[] args) {
        String str = "ajsfhsdhfasdfkjhsdfhsalkdjsfhdsfhjsklasjfjksfdghkslkdahjfjhsdgasjfhsdjfjshhfg";

//1.统计出现次数,就是权重,map存的是字符及对应权重
        HashMap<Character,Integer> map=new HashMap<>();
        for(int i=0;i<str.length();++i){
            Character ch=str.charAt(i);
            if(map.get(ch)==null){
                map.put(ch,1);
            }else{
                map.put(ch,map.get(ch)+1);
            }
        }
//2.树节点获取map字符和出现次数,加入列表
        ArrayList< HuffmanNode> arr=new ArrayList<>();
        for(Map.Entry<Character,Integer> en:map.entrySet()){
            //System.out.println("key:"+en.getKey()+"value"+en.getValue());
            HuffmanNode node=new HuffmanNode(en.getKey(),en.getValue());
            arr.add(node);
        }
//最小两个加入
        while(arr.size()>1){
            HuffmanNode[]data=getNode(arr);

            //这就是创建的新节点
            HuffmanNode root=new HuffmanNode(null,data[0].getNum()+data[1].getNum());
            root.setLeft(data[0]);
            root.setRight(data[1]);
            //新节点加入节点表
            arr.add(root);
        }
//构建成功
       HuffmanNode tree=arr.get(0);
        //System.out.println(tree);//最终Haffman树
//编码
        Map<Character,String> charMap=new HashMap<>();
        Map<String,Character> codeMaps=new HashMap<>();
        allViewMap(tree,"",charMap,codeMaps);
        String hafucode="";
        for(int i=0;i<str.length();++i){
            Character ch=str.charAt(i);
            hafucode+= charMap.get(ch);
        }
        System.out.println(hafucode.length()+"||"+str.length());
        System.out.println(hafucode);
        //先序遍历
        //allView(tree);
       // allViewCode(tree,"");
        String s=decode(hafucode,charMap);
        System.out.println("反编:"+s);
    }
    public static HuffmanNode []getNode(ArrayList<HuffmanNode>arr){
        HuffmanNode[]nodes=new HuffmanNode[2];
        int index1 ;
        int index2;
        if (arr.get(0).getNum() <= arr.get(1).getNum() ){
            index1=0;
            index2=1;
        }else{
            index1=1;
            index2=0;
        }
        //只是通过index取数据,通过取出的数据比较
        //然后
        for(int i=2;i<arr.size();++i){
            //当前比min1小
            if(arr.get(i).getNum()<arr.get(index1).getNum()){
                //先换index2
                    index2=index1;
                   index1=i;
             //当前比min1大比min2小
             //比min2大就不用换了
            }else if(arr.get(i).getNum()>=arr.get(index1).getNum() && arr.get(i).getNum()<=arr.get(index2).getNum()){
                index2=i;
            }
        }
        nodes[0]=arr.get(index1);
        nodes[1]=arr.get(index2);
        arr.remove(index1);
        //若index2删除前,index1删除了,remove(index2-1),因为index的缺失数组下标统一前移了
        //
        if(index2>index1){
            arr.remove(index2-1);
        }else{
            arr.remove(index2);
        }
        return nodes;
    }

    public static void treeShow( HuffmanNode tree){
        System.out.println();
    }
//    先序遍历
    public static  void allView( HuffmanNode tree){
        ///可以不判断空,最优树,根节点必不为空
        if(tree==null){
            return;
        }else{
            if(tree.getLeft()==null&&tree.getRight()==null){
                System.out.println(tree.getNum()+"  ||  "+tree.getCh());
            }else{
                allView(tree.getLeft());
                allView(tree.getRight());
            }

        }

    }

    public static  void allViewCode( HuffmanNode tree,String code){
        ///可以不判断空,最优树,根节点必不为空
        if(tree==null){
            return;
        }else{
            if(tree.getLeft()==null&&tree.getRight()==null){
                System.out.println(tree.getNum()+"  ||  "+tree.getCh()+"||"+code);
            }else{
                allViewCode(tree.getLeft(),code+"0");
                allViewCode(tree.getRight(),code+"1");
            }

        }
    }

//编码(由遍历而来的)
    public static  void allViewMap( HuffmanNode tree,String code,Map<Character,String> charMaps,Map<String,Character> codeMaps){
        ///可以不判断空,最优树,根节点必不为空
        if(tree==null){
            return;
        }else{
            if(tree.getLeft()==null&&tree.getRight()==null){
               // System.out.println(tree.getNum()+"  ||  "+tree.getCh()+"||"+code);
                charMaps.put(tree.getCh(),code);
                codeMaps.put(code,tree.getCh());
            }else{
                allViewMap(tree.getLeft(),code+"0",charMaps,codeMaps);
                allViewMap(tree.getRight(),code+"1",charMaps,codeMaps);
            }

        }
    }
//解码
    public static String decode(String str,Map<Character,String> map){
        String s="";
        while(str.length()>0) {
            for (Map.Entry<Character, String> entry : map.entrySet()) {
                if (str.startsWith(entry.getValue())) {
                    s += entry.getKey();
                    str = str.substring(entry.getValue().length());
                    break;
                }
            }
        }
        return s;
    }
}

package Huffman;

public class HuffmanNode{
    private Character ch;
    private int num;

    public HuffmanNode getLeft() {
        return left;
    }

    public void setLeft(HuffmanNode left) {
        this.left = left;
    }

    public HuffmanNode getRight() {
        return right;
    }

    public void setRight(HuffmanNode right) {
        this.right = right;
    }

    private HuffmanNode left;
    private HuffmanNode right;
    public HuffmanNode() {
    }

    public HuffmanNode(Character ch, int num) {
        this.ch = ch;
        this.num = num;
    }

    public Character getCh() {
        return ch;
    }

    public void setCh(Character ch) {
        this.ch = ch;
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    @Override
    public String toString() {
        return "HuffmanNode{" +
                "ch=" + ch +
                ", num=" + num +
                ", left=" + left +
                ", right=" + right +
                '}';
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值