哈夫曼树高级版——从文件中读取(java)

    这个高级版指的是从SourceFile文件中读字符,再将这些文字压缩到CodeFile文件中,最后从CodeFile文件中根据编码将其解压出来。
主要过程:
    1.先将从文件中读取的字符放入到HashMap中,用HashMap来记录每个字符出现的次数,相当于是权重,
    2.创建哈夫曼树,(过程跟前面写过的博客简易哈夫曼树是一样的,这里就不多说了)
    3.在得到每个叶子结点的编码的时候,再用一个HashMap将叶子结点和和它对应的编码存在一起
    4.然后再读一遍SourceFile,按照顺序将出现的文字的编码都用StringBuilder连接起来,存入到CodeFile文件中。这个StringBuilder就是文件中一一对应的编码
    5.最后根据CodeFile中的StringBuilder将文字解析出来,从字符的最左边开始,如果是0就走左子树,如果是1就走右子树,但是我们每找到一个叶子结点,都需要重新返回到整棵树的根结点,但是指向StringBuilder的指针位置不能变,所以就从主函数中使用一个循环,每当找到叶子结点的时候,就返回它在StringBuilder中的位置,以便于下次进行查找。

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

class Node1 {
    int weight;
    Node1 Lchild;
    Node1 Rchild;
    Node1 parent;
    String val;
    public  Node1(){}
    public Node1(String val,int weight) {
        this.val=val;
        this.weight=weight;
    }
}
public class HuffmanTree2 {
    static String res="";
    static HashMap<String,String> map1=new HashMap<>();
    public static void main(String[] args) throws IOException {
        //从文件中读字符
        FileInputStream fis=new FileInputStream("C:\\Users\\lenovo\\Desktop\\SourceFile.txt");//从这个文件中读取数据
        byte[] bytes=new byte[3];
        int readCount=0;
        HashMap<String, Integer> map=new HashMap<>();
        //将文字都读入map集合中,统计出现的数量
        System.out.println("SourceFile文件内:");
        while((readCount=fis.read(bytes))!=-1) {
            String s=new String(bytes,0,readCount);
            System.out.print(s);
            map.put(s,map.getOrDefault(s,0)+1);
        }
        System.out.println("");
        ArrayList<Node1> list=new ArrayList<>();
        //使用list将Map集合中的结点都存进去
        for(Map.Entry<String,Integer> m:map.entrySet()) {
            Node1 node1=new Node1(m.getKey(),m.getValue());
            list.add(node1);
        }
        list.sort((o1, o2) -> o1.weight-o2.weight);
        //建树
        Node1 root=CreateTree(list);
        String s="";
        System.out.println("每个字的编码:");
        print(root,s);
        //从文件中按照顺序拿到字符的编码
        FileInputStream fis2=new FileInputStream("C:\\Users\\lenovo\\Desktop\\SourceFile.txt");//从这个文件中读取数据
        byte[] bytes3=new byte[3];
        int readCount1=0;
        while((readCount1=fis2.read(bytes3))!=-1) {
            String s2=new String(bytes3,0,readCount1);
            res+=map1.get(s2);
        }

        //将编码写入到CodeFile文件内
        FileOutputStream fos=new FileOutputStream("C:\\Users\\lenovo\\Desktop\\CodeFile.txt");
        byte[] bytes1=res.getBytes();
        fos.write(bytes1);

        //从编码文件中读取编码
        FileInputStream fis1=new FileInputStream("C:\\Users\\lenovo\\Desktop\\CodeFile.txt");
        byte[] bytes2=new byte[2];
        int readcount=0;
        StringBuilder s1= new StringBuilder();
        while((readCount=fis1.read(bytes2))!=-1) {
            s1.append(bytes2[0]-48);
            if(readCount==2)s1.append(bytes2[1]-48);
        }
        System.out.println("CodeFile文件内:");
        System.out.println(s1);
        int i=0;
        System.out.println("解压后:");
        while(i<s1.length()) {
            i=jiema(s1,i,root);
        }

    }


    public static Node1 CreateTree(ArrayList<Node1> list) {
        while(list.size()!=1) {
            Node1 temp1=list.remove(0);
            Node1 temp2=list.remove(0);
            Node1 par=new Node1();
            par.weight=temp1.weight+temp2.weight;
            par.Lchild=temp1;
            par.Rchild=temp2;
            temp1.parent=par;
            temp2.parent=par;
            list.add(par);
            list.sort((o1, o2) -> o1.weight-o2.weight);
        }
        Node1 node=list.get(0);
        return node;
    }
    public static void  print(Node1 root,String s) {
        if(root==null)
            return ;
        if(root.Rchild==null&&root.Lchild==null) {//走到根结点的时候
            System.out.println(root.val+":"+s);
            map1.put(root.val,s);
        }
        print(root.Lchild,s+"0");
        print(root.Rchild,s+"1");
    }
    //按照压缩后的编码进行解码
    public static int jiema(StringBuilder s,int i,Node1 root) {
        if(root.Lchild==null&&root.Rchild==null) {
            System.out.print(root.val);
            return i;
        }
        if(s.charAt(i)-'0'==0&&i<s.length()) {
            return jiema(s,i+1,root.Lchild);
        }
        if(s.charAt(i)-'0'==1&&i<s.length()) {
            return jiema(s,i+1,root.Rchild);
        }
        return 0;
    }

}

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值