哈夫曼编码实验

哈夫曼的编码实验

一、哈夫曼编码介绍:

  • 1、哈夫曼树:

    (1)定义:假设有n个权值{w1, w2, ..., wn},试构造一棵含有n个叶子结点的二叉树,每个叶子节点带权威wi,则其中带权路径长度WPL最小的二叉树叫做最优二叉树或者哈夫曼树。

    (2)特点:哈夫曼树中没有度为1的结点,故由n0 = n2+1以及m= n0+n1+n2,n1=0可推出m=2*n0-1,即一棵有n个叶子节点的哈夫曼树共有2n-1个节点。
  • 2、哈夫曼编码步骤:
    • (1)计算字符出现的次数:
      • 假设我们现在有一段文档需要进行编码,我们现在需要对于每一个字符出现的次数进行统计,然后分别计算出其在这篇文档的权重,也就是频率,我们用下面的一段文字进行举例;
      • 在如下的文档中包括的字符有8个字母和2个空格,所以我们现在需要去统计这10个字符的个数,统计后的数据如下:
    • (2)对字符出现的次数作为一个权重,从小到大进行排序;
    • (3)依照排序结果从小到大根据以下规则进行造树:
      • a、最小的前两个数进行权重的相加,形成他们两个作为左子树和右子树的父结点,如果是左结点就标记为0,如果是右结点就标记为1
      • b、然后将父结点作为一个新的结点进入排序结果,之后进行重新排序(ps:假如出现添加后的父结点的权重和之前排序中的结点的权重相等的情况,两者的位置具体是对于建树没有影响的,但是在编程实现的过程中,程序需要将两者的位置进行确定)
      • c、重复上述过程,直到得到的父结点的权重为1。

代码构建过程:

字符出现的次数统计:

  String source="We go the hustler you've got to hustle There ain't no time for sleep Just keep on movin' do what you're doing ";
        String[] b = source.split("");
        int an=0;
        int bn=0;
        int cn=0;
        int dn=0;
        int en=0;
        int fn=0;
        int gn=0;
        int hn=0;
        int in=0;
        int jn=0;
        int kn=0;
        int ln=0;
        int mn=0;
        int nn=0;
        int on=0;
        int pn=0;
        int qn=0;
        int rn=0;
        int sn=0;
        int tn=0;
        int un=0;
        int vn=0;
        int wn=0;
        int xn=0;
        int yn=0;
        int zn=0;
        int zkongge=0;
        for (int i =0;i

2、哈夫曼编码&解码:

 private Map map=new HashMap<>();
    private Map ce=new HashMap<>();
    private PriorityQueue trees=new PriorityQueue<>();
    private String source;
    private String result;
    public void init(String source){
        this.source=source;
        char[] chars= source.toCharArray();
        for (char c :chars){
            if (!map.containsKey(c)){
                map.put(c,1);
            }else {
                map.put(c,map.get(c)+1);
            }
        }
        afterInit();
    }

    private void afterInit() {
        map.forEach((c,count)->{
            Node node=new Node<>();
            node.key=count;
            node.charData=c;

            Tree tree=new Tree();
            tree.setRoot(node);

            trees.add(tree);
        });
    }

    public void build(){
        while (this.trees.size()>1){
            Tree left=this.trees.poll();
            Tree right=this.trees.poll();

            Node node=new Node();
            node.key=left.getRoot().key+right.getRoot().key;
            node.leftChild=left.getRoot();
            node.rightChild=right.getRoot();

            left.setRoot(node);
            this.trees.add(left);
        }
    }
    public void encoding(){
        Tree tree=this.trees.peek();
        this.encoding(tree.getRoot(),"");
    }
    public String encodingResult(){
        StringBuilder sb=new StringBuilder();
        char[] chars= source.toCharArray();
        for (char c :chars){
            sb.append(ce.get(c)+' ');
        }
        return sb.toString();
    }
    private void encoding(Node node,String encoding){
        if (node!=null){
            if (node.leftChild==null && node.rightChild==null){
                ce.put(node.charData,encoding);
            }
            encoding(node.leftChild,encoding+"0");
            encoding(node.rightChild,encoding+"1");
        }
    }
    public void displayTree(){
        Tree tree=this.trees.peek();
        tree.inDisplay(tree.getRoot());
    }
    public void displayEncodeing(){
        ce.forEach((k,v)->{
            System.out.println(k+":"+v);
        });
    }

3、中序遍历建立哈夫曼树:

package Exp9.Hufman;
public class Tree implements Comparable{
    private Node root;

    public Node getRoot() {
        return root;
    }

    public void setRoot(Node root) {
        this.root = root;
    }
    /**
     *中序遍历法
     */
    public void inDisplay(Node node){
        if (node!=null){
            inDisplay(node.leftChild);
            System.out.println(node.key+":"+node.charData);
            inDisplay(node.rightChild);
        }
    }
    public void postDisplay(Node node){
        if (node!=null){
            postDisplay(node.leftChild);
            postDisplay(node.rightChild);
            System.out.print(node.key+":"+node.charData);

        }
    }
    @Override
    public int compareTo(Tree o) {
        if (this.root.key>o.root.key){
            return 1;
        }else if (this.root.key==o.root.key){
            return 0;
        }else {
            return -1;
        }
    }
}

完整代码

实验结果:

哈夫曼编码实验_第1张图片
哈夫曼编码实验_第2张图片
哈夫曼编码实验_第3张图片

参考资料:

  • 《Java程序设计与数据结构教程(第二版)》

  • 《Java程序设计与数据结构教程(第二版)》学习指导

  • java创建哈夫曼树和实现哈夫曼编码

你可能感兴趣的:(哈夫曼编码实验)