哈夫曼树简单java实现文本压缩与解压

本文介绍了如何使用哈夫曼树进行文本的压缩和解压。首先,阐述了哈夫曼树建立的过程,包括考虑是否包含所有ASCII字符,以及节点结构的初始化。接着,详细讲解了从文件读取内容、建立哈夫曼编码、压缩文件的步骤。在压缩环节,将字符的ASCII码转化为对应的哈夫曼编码,并以字节形式存储,同时输出哈夫曼编码以供解压时使用。在解压过程中,根据输出的哈夫曼编码重建哈夫曼树,从而解码文件。文章提供了完整的Java代码作为参考。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

哈夫曼树实现文本的压缩和解压

哈夫曼树这里就不在做相关介绍,网上也有很多哈夫曼树的介绍,这里主要介绍利用哈夫曼树进行文件的压缩与解压

首先是哈夫曼树的建立:ASCII 码一共有256个(常用的有128个)建立的时候可以选择一起将全部ASCII一起建立也可以选择按文档中出现的字符建立。虽然如果选择将所有字符一起建立的话可能会多很多,但由于在合并的之后所有0的点都会合并在一起所以对文件编码长度几乎没有影响。

下面是节点的结构与初始化

    class HTNODE{
        int weight;//权值
        int lchid;
        int rlight;
        int parent;
        int index;//下标
    }
    void InitHT(){
        for (int i=0;i<2*N-1;i++){
            htnode[i] = new HTNODE();
            htnode[i].lchid = -1;
            htnode[i].rlight = -1;
            htnode[i].parent = -1;
            htnode[i].weight = 0;
            htnode[i].index = i;
        }
    }

这里增加了一个下标,方便解压时的转化

前256个节点即为字符ASCII对应的下标,这样在压缩和解压时即可通过下标直接由节点转化为相应的字符

首先是从文件中按字符读取文本内容,每读取到一个字符其ASCII数值的结点下标权值相应加1

void readfile(){
        File file = new File("originalfile.txt");
        Reader reader;
        try {
            // 一次读一个字符
            reader = new InputStreamReader(new FileInputStream(file));
            int tempchar;
            while ((tempchar = reader.read()) != -1) {
                // 对于windows下,\r\n这两个字符在一起时,表示一个换行。
                // 但如果这两个字符分开显示时,会换两次行。
                // 因此,屏蔽掉\r,或者屏蔽\n。否则,将会多出很多空行。
                if (((char) tempchar) != '\r') {
                    oldfile += (char) tempchar;
                    htnode[tempchar].weight++;
                }
            }
            reader.close();
        }
        catch (IOException e) {
            System.out.println("打开文件失败\n");
        }
    }

接下来是寻找节点中权值最小的两个结点并返回下标

    int[] findmin(int i){
        int[] min = new int[2];
        min[0] = Integer.MAX_VALUE;
        min[1] = Integer.MAX_VALUE;
        int[] index = {0,0};
        for (int j=0; j<i; j++){
            if((min[0]>htnode[j].weight)&&(htnode[j].parent == -1)){
                min[1] = min[0];
                min[0] = htnode[j].weight;
                index[1] = index[0];
                index[0] = j;
            }
            else if((min[1]>htnode[j].weight)&&(htnode[j].parent == -1)){
                min[1] = htnode[j].weight;
		index[1] = j;
            }
        }
        return index;
    }

接下来是对结点的合并,前N个节点为基础结点,所以合并从下标为N的结点开始,寻找所有结点中权值最小的两个结点进行合并

    void CreatHT(){
        int[] min;
        for(int i=N;i<2*N-1;i++){
            min = findmin(i);
            htnode[min[0]].parent = i;
            htnode[min[1]].parent = i;
            htnode[i].lchid = min[0];
            htnode[i].rlight = min[1];
            htnode[i].weight = htnode[min[0]].weight + htnode[min[1]].weight;
   
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值