赫夫曼压缩以及解压(最后一位不补码导致的问题修补)

最开始最后一位没有补码,导致当最后一位出现诸如001,00这样的字节时,没有这么多的位数,导致报错,因此对代码进行修改。

原先代码

import java.util.*;

public class ReviewHuffman {
    static Map<Byte,String> map=new HashMap<>();
    public static void main(String[] args) {
        String s="i like like like java do you like a java";
        byte[] origin=s.getBytes();
//        //将数组转换成List集合
        List<HuffmanNode> list = rankHuffman(origin);
//        //将数组装入List集合,并生成赫夫曼树
        HuffmanNode huffman = createHuffman(list);
//        //得到每个叶子节点的路径,即赫夫曼表
        Map<Byte, String> huffmanTable = getHuffmanTable(huffman);
//        //将赫夫曼表转化为字节数组
        byte[] huffmanBytes = getHuffmanBytes(origin, huffmanTable);
//        System.out.println(Arrays.toString(huffmanBytes));

        //封装好的赫夫曼压缩
//        byte[] bytes = huffmanZip(origin);
//        System.out.println(Arrays.toString(bytes));

        //赫夫曼压缩后解压
        byte[] bytes = deCodeHuffman(huffmanTable, huffmanBytes);
        System.out.println(new String(bytes));
    }
    /********************************************压缩*************************************************/
    //封装好了的赫夫曼压缩
    private static byte[] huffmanZip(byte[] origin){
        //将数组转换成List集合
        List<HuffmanNode> list = rankHuffman(origin);
        //将数组装入List集合,并生成赫夫曼树
        HuffmanNode huffman = createHuffman(list);
        //得到每个叶子节点的路径,即赫夫曼表
        Map<Byte, String> huffmanTable = getHuffmanTable(huffman);
        //将赫夫曼表转化为字节数组
        return getHuffmanBytes(origin, huffmanTable);
    }

    //先得到每个字符对应的出现次数
    private static List<HuffmanNode> rankHuffman(byte[] origin){
        Map<Byte,Integer> map=new HashMap<>();
        //封装每个字符出现的次数
        for (int i=0;i<origin.length;i++){
            if (map.get(origin[i])==null){
                map.put(origin[i],1);
            }else {
                map.put(origin[i],map.get(origin[i])+1);
            }
        }
        //存入List中
        List<HuffmanNode> list=new ArrayList<>();
        for (Map.Entry<Byte,Integer> tmp:map.entrySet()){
            list.add(new HuffmanNode(tmp.getKey(),tmp.getValue()));
        }
        return list;
    }
    //将List排序,并生成赫夫曼树
    private static HuffmanNode createHuffman(List<HuffmanNode> list){
        while (list.size()>1){
            Collections.sort(list);
            HuffmanNode leftNode=list.get(0);
            HuffmanNode rightNode=list.get(1);
            HuffmanNode parent=new HuffmanNode(null,leftNode.weight+rightNode.weight);
            //将得到的左右节点放在新的父节点下,并从原数组移除左右节点,放入父节点
            parent.left=leftNode;
            parent.right=rightNode;
            list.remove(leftNode);
            list.remove(rightNode);
            list.add(parent);
        }
        return list.get(0);
    }
    /**
     *
     * @param huffmanNode 生成的赫夫曼树的根节点
     * @param code 定义准则,左边为0 右边为1
     * @param path 每个叶子节点的路径
     * @return 返回map集合,里面装有所有叶子节点和它对应的路径
     */
    //得到赫夫曼表
    private static void getHuffmanTable(HuffmanNode huffmanNode,String code,StringBuilder path){
        StringBuilder builder=new StringBuilder(path);
        builder.append(code);
        if (huffmanNode!=null){
            //等于空说明为非叶子节点需要递归寻找
            if (huffmanNode.data==null){
                getHuffmanTable(huffmanNode.left,"0",builder);
                getHuffmanTable(huffmanNode.right,"1",builder);
            }else {//叶子节点,找到了一个了,需放入
                map.put(huffmanNode.data,builder.toString());
            }
        }
    }
    //重载赫夫曼树表
    private static Map<Byte,String> getHuffmanTable(HuffmanNode huffmanNode){
        StringBuilder strBu=new StringBuilder();
        getHuffmanTable(huffmanNode,"",strBu);
        return map;
    }
    //将赫夫曼表转化为字节数组
    private static byte[] getHuffmanBytes(byte[] origin,Map<Byte,String> map){
        byte[] tmp;
        StringBuilder stringBuilder=new StringBuilder();
        //先将赫夫曼表拼接
        for (int i=0;i<origin.length;i++){
            stringBuilder.append(map.get(origin[i]));
        }
        System.out.println(stringBuilder.toString());
        //算出字节总数
        int count=stringBuilder.length()/8;
        if (count==0){
            tmp=new byte[count];
        }else {
            tmp=new byte[count+1];
        }
        //将上面的字符stringBuilder拆分放进tmp中 每8个一组, (注意要将其转为2进制转换!!!)
        int index=0;//记录放了多少个字节了
        for (int i=0;i<stringBuilder.length();i+=8){
            if (i+8<stringBuilder.length()){
                tmp[index++]=(byte)Integer.parseInt(stringBuilder.substring(i,i+8),2);
            }else {
                tmp[index++]=(byte)Integer.parseInt(stringBuilder.substring(i),2);
            }
        }
        //以上完成后就将字符分割开,放进字节中了
        return tmp;
    }
    /**************************************************解压************************************************************/
    /**
     * 功能: 对赫夫曼压缩后的数据进行解压
     * @param originMap 数据和赫夫曼字符串的对应关系
     * @param huffZip 赫夫曼压缩后生成的数组
     * @return 返回原始(被压缩前的数组)
     */
    //对压缩的赫夫曼解码
    private static byte[] deCodeHuffman(Map<Byte,String> originMap,byte[] huffZip){
        //将原本的key value 转置为 value key
        Map<String,Byte> revMap=new HashMap<>();
        for (Map.Entry<Byte,String> t:originMap.entrySet()){
            revMap.put(t.getValue(),t.getKey());
        }
        StringBuilder all=new StringBuilder();
        //将赫夫曼数组转换成字符串拼接起来
        for (int i=0;i<huffZip.length;i++){
            //最后一次不用补位,是多少就是多少,其余的不足需要补高位
            all.append(bitToBitString(i != huffZip.length - 1,huffZip[i]));
        }
        //当下的字符串
        String tmp;
        //往后移动的距离
        int count;
        //从map中获取到的源字节
        Byte t;
        //源数组
        byte[] bytes;
        List<Byte> list=new ArrayList<>();
        for (int i=0;i<all.length();i=i+count){
            count=1;
            while (true){
                tmp=all.substring(i,i+count);
                t=revMap.get(tmp);
                if (t==null){//如果为空说明里面没有对应的哈夫曼表
                    count++;
                }else {
                    //不为空说明找到了,添加进去,跳出此次while循环
                    list.add(t);
                    break;
                }
            }
        }
        bytes=new byte[list.size()];
        for (int i=0;i< list.size();i++){
            bytes[i]=list.get(i);
        }
        return bytes;
    }
    /**
     * 功能:将二进制字节转成字符串
     * @param flag 标志高位是否需要补位,如果为true则需要补位,如果是false则不补位
     * @param huff 传入的byte
     * @return 传入的byte的二进制字符串 (补码形式返回)
     */
    private static String bitToBitString(boolean flag,byte huff){
        int tmp=huff;
        //flag为true进行补位,或上就行
         if (flag){
            tmp |=256;  //256 为 1_0000_0000 tmp与其或了之后,就能达到补位的效果
         }
        String str=Integer.toBinaryString(tmp);
        //因为是取的int的补码,所以我们只需要后面8位,前面8位截取掉
        if (str.length()>8) {
            return str.substring(str.length() - 8);
        }else {
            return str;
        }
    }
}
class HuffmanNode implements Comparable<HuffmanNode>{
    HuffmanNode left;
    HuffmanNode right;
    int weight;
    Byte data;

    public HuffmanNode(Byte data,int weight) {
        this.weight = weight;
        this.data = data;
    }

    @Override
    public String toString() {
        return "HuffmanNode{" +
                "data=" + data +
                ",weight=" + weight +
                '}';
    }

    @Override
    public int compareTo(HuffmanNode o) {
        return this.weight-o.weight;
    }
}

修改代码

修补思想:原先最后一位没有补码,现在对每一位都补位。这样的话到最后一位时,判断规则需做出改变,不能从前往后了,需从后往前,找到就直接退出循环。

                if (all.length()-i>8){
                    tmp=all.substring(i,i+count);
                }else {//判断最后一个了,从后往前,找出来了就直接退出
                    tmp=all.substring(all.length()-count);
                    flag=true;
                }

修改后压缩及解压文件代码:

package syf.huffmantree;

import java.io.*;
import java.util.*;

public class ReviewHuffman {
    static Map<Byte,String> map=new HashMap<>();
    public static void main(String[] args) {

//        String s="i like like like java do you like a java";
//        byte[] origin=s.getBytes();
//        //将数组转换成List集合
//        List<HuffmanNode> list = rankHuffman(origin);
//        //将数组装入List集合,并生成赫夫曼树
//        HuffmanNode huffman = createHuffman(list);
//        //得到每个叶子节点的路径,即赫夫曼表
//        Map<Byte, String> huffmanTable = getHuffmanTable(huffman);
//        //将赫夫曼表转化为字节数组
//        byte[] huffmanBytes = getHuffmanBytes(origin, huffmanTable);
//        System.out.println(Arrays.toString(huffmanBytes));

        /* 注释掉字符串压缩和解压
        //封装好的赫夫曼压缩,传入待压缩的文件的字节数组
        byte[] bytes = huffmanZip(origin);
        System.out.println(Arrays.toString(bytes));
        //赫夫曼压缩后的解压
        byte[] deByte = deCodeHuffman(map, bytes);
        System.out.println(new String(deByte));
        */

        //文件的压缩
//        String src="src/test/java/syf/TestHuffman/out682.txt";
//        String dest="src/test/java/syf/TestHuffman/out682.zip";
//        zipFile(src,dest);
//        System.out.println("压缩成功!!");
        //文件的解压
        String src="src/test/java/syf/TestHuffman/out682.zip";
        String dest="src/test/java/syf/TestHuffman/out6823.txt";
        unzipFile(src,dest);
        System.out.println("解压成功");
    }
    /********************************************压缩*************************************************/
    //封装好了的赫夫曼压缩
    private static byte[] huffmanZip(byte[] origin){
        //将数组转换成List集合
        List<HuffmanNode> list = rankHuffman(origin);
        //将数组装入List集合,并生成赫夫曼树
        HuffmanNode huffman = createHuffman(list);
        //得到每个叶子节点的路径,即赫夫曼表
        Map<Byte, String> huffmanTable = getHuffmanTable(huffman);
        //将赫夫曼表转化为字节数组
        return getHuffmanBytes(origin, huffmanTable);
    }

    //先得到每个字符对应的出现次数
    private static List<HuffmanNode> rankHuffman(byte[] origin){
        Map<Byte,Integer> map=new HashMap<>();
        //封装每个字符出现的次数
        for (int i=0;i<origin.length;i++){
            if (map.get(origin[i])==null){
                map.put(origin[i],1);
            }else {
                map.put(origin[i],map.get(origin[i])+1);
            }
        }
        //存入List中
        List<HuffmanNode> list=new ArrayList<>();
        for (Map.Entry<Byte,Integer> tmp:map.entrySet()){
            list.add(new HuffmanNode(tmp.getKey(),tmp.getValue()));
        }
        return list;
    }
    //将List排序,并生成赫夫曼树
    private static HuffmanNode createHuffman(List<HuffmanNode> list){
        while (list.size()>1){
            Collections.sort(list);
            HuffmanNode leftNode=list.get(0);
            HuffmanNode rightNode=list.get(1);
            HuffmanNode parent=new HuffmanNode(null,leftNode.weight+rightNode.weight);
            //将得到的左右节点放在新的父节点下,并从原数组移除左右节点,放入父节点
            parent.left=leftNode;
            parent.right=rightNode;
            list.remove(leftNode);
            list.remove(rightNode);
            list.add(parent);
        }
        return list.get(0);
    }
    /**
     * @param huffmanNode 生成的赫夫曼树的根节点
     * @param code 定义准则,左边为0 右边为1
     * @param path 每个叶子节点的路径
     * @return 返回map集合,里面装有所有叶子节点和它对应的路径
     */
    //得到赫夫曼表
    private static void getHuffmanTable(HuffmanNode huffmanNode,String code,StringBuilder path){
        StringBuilder builder=new StringBuilder(path);
        builder.append(code);
        if (huffmanNode!=null){
            //等于空说明为非叶子节点需要递归寻找
            if (huffmanNode.data==null){
                getHuffmanTable(huffmanNode.left,"0",builder);
                getHuffmanTable(huffmanNode.right,"1",builder);
            }else {//叶子节点,找到了一个了,需放入
                map.put(huffmanNode.data,builder.toString());
            }
        }
    }
    //重载赫夫曼树表
    private static Map<Byte,String> getHuffmanTable(HuffmanNode huffmanNode){
        StringBuilder strBu=new StringBuilder();
        getHuffmanTable(huffmanNode,"",strBu);
        return map;
    }
    //将赫夫曼表转化为字节数组
    private static byte[] getHuffmanBytes(byte[] origin,Map<Byte,String> map){
        byte[] tmp;
        StringBuilder stringBuilder=new StringBuilder();
        //先将赫夫曼表拼接
        for (int i=0;i<origin.length;i++){
            stringBuilder.append(map.get(origin[i]));
        }
//        System.out.println(stringBuilder.toString());
        //算出字节总数
        int count=stringBuilder.length()%8;//除出来等于0代表为8的倍数,否则加1
        if (count==0){
            tmp=new byte[stringBuilder.length()/8];
        }else {
            tmp=new byte[stringBuilder.length()/8+1];
        }
        //将上面的字符stringBuilder拆分放进tmp中 每8个一组, (注意要将其转为2进制转换!!!)
        int index=0;//记录放了多少个字节了
        for (int i=0;i<stringBuilder.length();i+=8){
            if (i+8>stringBuilder.length()){//不够8位
                tmp[index]=(byte)Integer.parseInt(stringBuilder.substring(i),2);
            }else {
                tmp[index]=(byte)Integer.parseInt(stringBuilder.substring(i,i+8),2);
            }
            index++;
        }
        //以上完成后就将字符分割开,放进字节中了
        return tmp;
    }
    /**************************************************解压************************************************************/
    /**
     * 功能: 对赫夫曼压缩后的数据进行解压
     * @param originMap 数据和赫夫曼字符串的对应关系
     * @param huffZip 赫夫曼压缩后生成的数组
     * @return 返回原始(被压缩前的数组)
     */
    //对压缩的赫夫曼解码
    private static byte[] deCodeHuffman(Map<Byte,String> originMap,byte[] huffZip){
        //将原本的key value 转置为 value key
        Map<String,Byte> revMap=new HashMap<>();
        for (Map.Entry<Byte,String> t:originMap.entrySet()){
            revMap.put(t.getValue(),t.getKey());
        }
        StringBuilder all=new StringBuilder();
        //将赫夫曼数组转换成字符串拼接起来
        for (int i=0;i<huffZip.length;i++){
            //最后一次不用补位,是多少就是多少,其余的不足需要补高位
            //最后一次需要补位,因为当最后一位为例如 000时,不补位只有一个0 不正确
            all.append(bitToBitString(huffZip[i]));
        }
        //当下的字符串
        String tmp;
        //往后移动的距离
        int count;
        //从map中获取到的源字节
        Byte t;
        //源数组
        byte[] bytes;
        List<Byte> list=new ArrayList<>();
        boolean flag=false;
        for (int i=0;i<all.length();){
            count=1;
            while (true){
                if (all.length()-i>8){
                    tmp=all.substring(i,i+count);
                }else {//判断最后一个了,从后往前,找出来了就直接退出
                    tmp=all.substring(all.length()-count);
                    flag=true;
                }
                t=revMap.get(tmp);
                if (t==null){//如果为空说明里面没有对应的哈夫曼表
                    count++;
                }else {
                    //不为空说明找到了,添加进去,跳出此次while循环
                    list.add(t);
                    break;
                }
            }
            i+=count;
            if (flag)//如果为true跳出,则说明为最后一个,且已经找到。直接跳出循环
                break;
        }
        bytes=new byte[list.size()];
        for (int i=0;i< list.size();i++){
            bytes[i]=list.get(i);
        }
        return bytes;
    }
    /**
     * 功能:将二进制字节转成字符串
//     * @param flag 标志高位是否需要补位,如果为true则需要补位,如果是false则不补位
     * @param huff 传入的byte
     * @return 传入的byte的二进制字符串 (补码形式返回)
     */
    private static String bitToBitString(byte huff){
        int tmp=huff;
        //flag为true进行补位,或上就行
        tmp |=256;  //256 为 1_0000_0000 tmp与其或了之后,就能达到补位的效果
        String str=Integer.toBinaryString(tmp);
        //因为是取的int的补码,所以我们只需要后面8位,前面8位截取掉
        return str.substring(str.length() - 8);
    }
    /******************************************文件压缩****************************************************/
    /**
     *
     * @param srcFile 要进行压缩的文件路径
     * @param destFile 压缩后文件放置的位置
     */
    private static void zipFile(String srcFile,String destFile){
        //创建缓冲流
        BufferedInputStream bi=null;
        BufferedOutputStream bo=null;
        //对象流,可按照写入顺序读出。一个为文件字节,一个为存储规则map
        ObjectOutputStream oos=null;
        //读取字节的数组
        byte[] getBytes;
        try {
            //将源文件的流读进来
            bi=new BufferedInputStream(new FileInputStream(srcFile));
            //获取源文件的字节大小,进行数组创建
            getBytes=new byte[bi.available()];
            //将文件读进getBytes
            bi.read(getBytes);
            //对文件进行压缩,得到赫夫曼压缩后数组
            byte[] huffmanBytes = huffmanZip(getBytes);
            //创建输出缓冲流
            bo=new BufferedOutputStream(new FileOutputStream(destFile));
            //使用对象流输出,方便按对象直接读取
            oos=new ObjectOutputStream(bo);
            oos.writeObject(huffmanBytes);
            oos.flush();
            oos.writeObject(map);
            oos.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (oos!=null) {
                try {
                    oos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bo!=null){
                try {
                    bo.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bi!=null) {
                try {
                    bi.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    /******************************************文件解压****************************************************/
    /**
     *
     * @param srcFile 要进行解压的文件路径
     * @param destFile 解压后文件放置的位置
     */
    private static void unzipFile(String srcFile,String destFile){
        //创建缓冲流
        BufferedInputStream bi=null;
        BufferedOutputStream bo=null;
        //对象流,可按照写入顺序读出。一个为文件字节,一个为存储规则map
        ObjectInputStream ois=null;
        //读取字节的数组
        byte[] huffmanBytes;
        //压缩规则
        Map<Byte,String> zipRule;
        try {
            //将待解压的文件读进来
            bi=new BufferedInputStream(new FileInputStream(srcFile));
            //读成对象流,可以对象写出
            ois=new ObjectInputStream(bi);
            //写出压缩后的赫夫曼表,,按写入顺序读出
            huffmanBytes=(byte[]) ois.readObject();
            //写出压缩规则
            zipRule= (Map<Byte,String>)ois.readObject();
            //解压,得到原始字节
            byte[] bytes = deCodeHuffman(zipRule, huffmanBytes);
            //定义解压位置开始输出文件
            bo=new BufferedOutputStream(new FileOutputStream(destFile));
            bo.write(bytes);
            bo.flush();
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (ois!=null) {
                try {
                    ois.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bo!=null){
                try {
                    bo.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bi!=null) {
                try {
                    bi.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
class HuffmanNode implements Comparable<HuffmanNode>{
    HuffmanNode left;
    HuffmanNode right;
    int weight;
    Byte data;

    public HuffmanNode(Byte data,int weight) {
        this.weight = weight;
        this.data = data;
    }

    @Override
    public String toString() {
        return "HuffmanNode{" +
                "data=" + data +
                ",weight=" + weight +
                '}';
    }

    @Override
    public int compareTo(HuffmanNode o) {
        return this.weight-o.weight;
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是使用夫曼树进行文件压缩的 C 语言示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_TREE_HT 100 typedef struct MinHeapNode { char data; unsigned freq; struct MinHeapNode *left, *right; } MinHeapNode; typedef struct MinHeap { unsigned size; unsigned capacity; MinHeapNode **array; } MinHeap; typedef struct HuffmanNode { char data; char *code; struct HuffmanNode *left, *right; } HuffmanNode; MinHeapNode* newMinHeapNode(char data, unsigned freq) { MinHeapNode* node = (MinHeapNode*) malloc(sizeof(MinHeapNode)); node->left = node->right = NULL; node->data = data; node->freq = freq; return node; } MinHeap* createMinHeap(unsigned capacity) { MinHeap* minHeap = (MinHeap*) malloc(sizeof(MinHeap)); minHeap->size = 0; minHeap->capacity = capacity; minHeap->array = (MinHeapNode**) malloc(minHeap->capacity * sizeof(MinHeapNode*)); return minHeap; } void swapMinHeapNode(MinHeapNode** a, MinHeapNode** b) { MinHeapNode* t = *a; *a = *b; *b = t; } void minHeapify(MinHeap* minHeap, int idx) { int smallest = idx; int left = 2 * idx + 1; int right = 2 * idx + 2; if (left < minHeap->size && minHeap->array[left]->freq < minHeap->array[smallest]->freq) smallest = left; if (right < minHeap->size && minHeap->array[right]->freq < minHeap->array[smallest]->freq) smallest = right; if (smallest != idx) { swapMinHeapNode(&minHeap->array[smallest], &minHeap->array[idx]); minHeapify(minHeap, smallest); } } int isSizeOne(MinHeap* minHeap) { return (minHeap->size == 1); } MinHeapNode* extractMin(MinHeap* minHeap) { MinHeapNode* temp = minHeap->array[0]; minHeap->array[0] = minHeap->array[minHeap->size - 1]; --minHeap->size; minHeapify(minHeap, 0); return temp; } void insertMinHeap(MinHeap* minHeap, MinHeapNode* minHeapNode) { ++minHeap->size; int i = minHeap->size - 1; while (i && minHeapNode->freq < minHeap->array[(i - 1) / 2]->freq) { minHeap->array[i] = minHeap->array[(i - 1) / 2]; i = (i - 1) / 2; } minHeap->array[i] = minHeapNode; } void buildMinHeap(MinHeap* minHeap) { int n = minHeap->size - 1; int i; for (i = (n - 1) / 2; i >= 0; --i) minHeapify(minHeap, i); } void printArr(int arr[], int n) { int i; for (i = 0; i < n; ++i) printf("%d", arr[i]); printf("\n"); } int isLeaf(MinHeapNode* root) { return !(root->left) && !(root->right); } MinHeap* createAndBuildMinHeap(char data[], int freq[], int size) { MinHeap* minHeap = createMinHeap(size); for (int i = 0; i < size; ++i) minHeap->array[i] = newMinHeapNode(data[i], freq[i]); minHeap->size = size; buildMinHeap(minHeap); return minHeap; } MinHeapNode* buildHuffmanTree(char data[], int freq[], int size) { MinHeapNode *left, *right, *top; MinHeap* minHeap = createAndBuildMinHeap(data, freq, size); while (!isSizeOne(minHeap)) { left = extractMin(minHeap); right = extractMin(minHeap); top = newMinHeapNode('$', left->freq + right->freq); top->left = left; top->right = right; insertMinHeap(minHeap, top); } return extractMin(minHeap); } void printCodes(MinHeapNode* root, int arr[], int top, HuffmanNode **huffmanTable) { if (root->left) { arr[top] = 0; printCodes(root->left, arr, top + 1, huffmanTable); } if (root->right) { arr[top] = 1; printCodes(root->right, arr, top + 1, huffmanTable); } if (isLeaf(root)) { HuffmanNode *node = (HuffmanNode*) malloc(sizeof(HuffmanNode)); node->data = root->data; node->code = (char*) malloc((top+1) * sizeof(char)); memcpy(node->code, arr, (top+1) * sizeof(char)); huffmanTable[node->data] = node; } } void HuffmanCodes(char data[], int freq[], int size, HuffmanNode **huffmanTable) { int arr[MAX_TREE_HT], top = 0; MinHeapNode* root = buildHuffmanTree(data, freq, size); printCodes(root, arr, top, huffmanTable); } void compressFile(char *inputFile, char *outputFile, HuffmanNode **huffmanTable) { FILE *inFile = fopen(inputFile, "r"); FILE *outFile = fopen(outputFile, "wb"); char c, byte = 0; int bitCount = 0; while ((c = fgetc(inFile)) != EOF) { HuffmanNode *node = huffmanTable[c]; for (int i = 0; i < strlen(node->code); i++) { byte <<= 1; byte |= node->code[i] - '0'; bitCount++; if (bitCount == 8) { fwrite(&byte, 1, 1, outFile); byte = 0; bitCount = 0; } } } if (bitCount > 0) { byte <<= (8 - bitCount); fwrite(&byte, 1, 1, outFile); } fclose(inFile); fclose(outFile); } int main() { char data[] = {'A', 'B', 'C', 'D', 'E', 'F'}; int freq[] = {5, 9, 12, 13, 16, 45}; int size = sizeof(data) / sizeof(data[0]); HuffmanNode *huffmanTable[256] = {NULL}; HuffmanCodes(data, freq, size, huffmanTable); char *inputFile = "input.txt"; char *outputFile = "output.bin"; compressFile(inputFile, outputFile, huffmanTable); return 0; } ``` 这个示例代码是以字符为单位进行压缩的,可以根据实际需要进行修改和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

syf_wfl

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值