精华内容
下载资源
问答
  • 实验目的:理解哈弗曼信源编码算法,并能应用于文件压缩中。 实验内容:写出程序,利用哈弗曼编码实现对文件的压缩,并能解压文件。 实验步骤: 1、压缩 (1) 统计原始文件中各字节出现的概率(次数); (2) 采用...
  • 草稿版代码 内容超详细 可压缩任何文件类型 亲测可用 100%还原
  • 用面向对象的程序设计思想自己动手写压缩软件,采用了优先队列这一很好的数据结构实现的贪心算法构造Huffman树,能打印Huffman树,显示编码表,压缩文件和解压缩文件,采用UTF-8字符集,支持中文文件
  • 文档为Linux下bz2压缩格式,winfows大部分压缩软件应该可以识别。内含可执行jar,eclipse工程文件,和readme。动态哈夫曼树,算法注释详细,用Javafx8做了个GUI界面,所以如果main无法运行可能是需要java8,如果不想...
  • 哈夫曼编码压缩.rar

    2019-12-13 10:34:30
    哈夫曼编码实训,通过构建哈夫曼树及哈夫曼编码,实现无损压缩压缩,内含完整注释,代码简便容易理解(100%运行成功+代码+简单窗口美化)~~~仅供学习交流,请勿他用!!
  • 哈夫曼编码用于解压和压缩的示例代码,非常简单易懂,C风格C++写法。
  • 草稿版代码 内容超详细 可压缩任何文件类型 本人亲测 但代码有些部分时间复杂度待优化
  • 哈夫曼编码和解码代码,利用哈夫曼编码压缩和解压文件的小工具。
  • 使用哈夫曼编码统计字符的频率作为权值来实现压缩技术 ,包括哈夫曼树的创建,构造哈夫曼编码,使用哈夫曼编码压缩文件,和解压文件
  • 利用二叉树哈夫曼编码实现对文件压缩以及解压缩
  • 利用哈夫曼编码压缩文本

    千次阅读 多人点赞 2020-04-12 16:27:21
    文章目录使用哈夫曼编码进行压缩文本文本内容读取文件内容至内存中遍历文本内容,获取每个字符对应出现概率值建立哈夫曼树获取哈夫曼编码将转换后的编码写入新文件检测压缩率利用编码文件进行还原文本完整code ...

    使用哈夫曼编码进行压缩文本

    文本内容

    Even though neural network-based models have achieved
    a lot, there are several important things that have not been
    taken into consideration. Firstly, as shown in Figure 1, each
    block is represented as a low-dimensional embedding with
    manually selected features, which will cause the loss of
    much semantic information. Secondly, the order of the nodes
    plays an important role in representing binary functions,
    while previous approaches did not design methods to extract
    it. To solve these two problems, we propose an overall
    framework with three components: semantic-aware modeling,
    structural-aware modeling, and order-aware modeling.

    读取文件内容至内存中

    char *read_file(const char *filename)     ///从文件中读取字符串
    {
        FILE *fp = NULL;
        char buf[256];
        int len = 0;
        char *x = new char [10000];
        *x = '\0';
    
        if((fp = fopen(filename, "r"))==NULL)
        {
            perror("can't open the file");
            exit(1);
        }
        while(fgets(buf, 255, fp) != NULL)
        {
            len = strlen(buf);
            //printf("%d", len);
            if(buf[len-1] == '\n')
            {
                buf[len-1] = '\0';
            }
            //printf("%s\n", buf);
            strcat(x, buf);
        }
        //printf("%s\n", x);
        fclose(fp);
        return x;
    }
    
    

    遍历文本内容,获取每个字符对应出现概率值

    int samechar(char *x)     ///该函数将不同字符出现的次数记录下来
    {
        int flag;
        int n=0;
        tree_huffman[n].c = x[0];
        tree_huffman[n].w = 1.0;
        int l=strlen(x);
        for(int i=1;i<l;i++)
        {
            int j;
            flag=0;
            for(j=0;j<=n;j++)
            {
                if(x[i]==tree_huffman[j].c)
                {
                    flag=1;
                    tree_huffman[j].w++;
                    break;
                }
            }
            if(!flag)
            {
                n++;
                tree_huffman[n].c=x[i];
                tree_huffman[n].w=1.0;
            }
        }
        return n+1;
    }
    

    建立哈夫曼树

    • 首先给所有节点的权值由小到大排序;
    • 取出最小的两个节点,将它们的权值相加,得到一个新节点
    • 使用这个新节点代替两个原来的节点
    • 继续排序,替换
    • 直到整个队列中只有一个节点
    • 这就构成了一棵哈夫曼树
    int cmp(Tree a, Tree b)
    {
        return a.w<b.w;
    }
    
    int create_huffman(int n)   ///构建哈夫曼树
    {
        int rear = n, font = 0;
        Tree last;
        while(rear > font)
        {
            sort(tree_huffman+font, tree_huffman+rear, cmp);
            last = tree_huffman[font];
            last.l = font;
            font++;
            if (rear <= font)
                break;
            else
            {
                Tree t = tree_huffman[font];
                last.w += t.w;
                last.c = '\0';
                last.r = font;
                last.par = -1;
                font++;
                tree_huffman[rear++] = last;
            }
        }
        for(int i=0;i<rear;++i)
        {
            if(tree_huffman[i].l >= 0)
            {
                int lchild = tree_huffman[i].l;
                tree_huffman[lchild].par = i;
            }
            if(tree_huffman[i].r >= 0)
            {
                int rchild = tree_huffman[i].r;
                tree_huffman[rchild].par = i;
            }
        }
        //for(int i=0;i<rear;++i)
            //printf("%d, %c,%.2lf,%d,%d,%d\n", i, tree_huffman[i].c, tree_huffman[i].w, tree_huffman[i].l, tree_huffman[i].r, tree_huffman[i].par);
        return rear;
    
    }
    

    获取哈夫曼编码

    • 采用递归获取哈夫曼编码
    • 需要注意一个问题:使用char *进行递归时,系统只会给char *开辟一块内存
    • 这样造成哈夫曼编码前缀相同
    • 解决问题方法:换用string,string每次都开辟新内存来递归;或每次递归时给char *开辟新内存
    void output_tree_code(Tree &temp, char *code)
    {
        if(temp.l == -1 && temp.r == -1)
        {
            printf("%s\n", code);
            strcpy(temp.flag, code);
            return;
        }
        char t1[256], t2[256];
        strcpy(t1, code);
        strcpy(t2, code);
        output_tree_code(tree_huffman[temp.l], strcat(t1, "0"));
        output_tree_code(tree_huffman[temp.r], strcat(t2, "1"));
    }
    

    将转换后的编码写入新文件

    • 将哈夫曼编码每八位截取,不足8位的后面补零
    • 再将单个字节写入二进制文件
    void wfile(const char *filename1, const char *filename2, int n)
    {
        FILE *fp = NULL;
        fp = fopen(filename2, "wb");
        char *buf = read_file(filename1);
        char *temp = new char [10000];
        temp[0] = '\0';
        for(int i=0;i<int(strlen(buf));++i)
        {
            for(int j=0;j<n;++j)
            {
                if(buf[i] == tree_huffman[j].c)
                {
                    strcat(temp, tree_huffman[j].flag);
                    break;
                }
            }
        }
        printf("%s\n", temp);
        int len = 0;
        if(strlen(temp) % 8 == 0)
            len = strlen(temp) / 8;
        else
        {
            len = strlen(temp) / 8 + 1;
            while(strlen(temp) % 8 != 0)
            {
                strcat(temp, "0");
            }
        }
    
        for(int i=0;i<len;++i)
        {
            int a = 0;
            for(int j=0;j<8;++j)
            {
                int ca = temp[i*8+j] - '0';
                a += ca * pow(2, 7-j);
                //printf("%d\t", ca * pow(2, 8-j));
            }
            fwrite(&a, 1, 1, fp);
        }
        fclose(fp);
    }
    

    检测压缩率

    • 查看压缩文件2.huffman的大小

    • 查看原文件大小

    • 342/636 = 53%,也就是说压缩率为47%,压缩了将近一半的大小,就压缩率而言,相当可观。

    利用编码文件进行还原文本

    • 读取哈夫曼编码还原文本;
    • 从第一个字符开始读,如果为0,则向根节点的左子树走,如果为1,则向根节点的右子树走;
    • 每读取一个字符,进行一次移动操作;
    • 直到移动至叶子节点,该节点的左右子树均为空,递归结束,输出该节点的字符;
    • 继续读取下一个字符;
    • 直到所有字符读取完毕;
    void unzip_huffman(const char *filename, int root)
    {
        FILE *fp = NULL;
        if((fp = fopen(filename, "rb"))==NULL)
        {
            perror("can't open the file");
            exit(1);
        }
        int cb[10000];
        int num = 0;
        while(!feof(fp))
        {
            int element = getc(fp);
            //printf("%d\t", element);
            if(element != -1)
            {
                for(int i=0;i<8;++i)
                {
                    int t = element % 2;
                    element = element / 2;
                    cb[num++] = t;
                }
            }
        }
        int ccb[10000];
        int xnum = 0;
        for(int i=0;i<num/8;++i)
        {
            for(int j=0;j<8;++j)
            {
                ccb[xnum++] = cb[i*8+7-j];
            }
        }
        fclose(fp);
        char ss[10000] = "\0";
        int sr = 0;
        num = 0;
        int rt = root;
        while(num < xnum)
        {
            while(tree_huffman[rt].l != -1 && tree_huffman[rt].r != -1)
            {
                if(ccb[num] == 0)
                {
                    rt = tree_huffman[rt].l;
                }
                else if(ccb[num] == 1)
                {
                    rt = tree_huffman[rt].r;
                }
                num++;
            }
            ss[sr++] = tree_huffman[rt].c;
            //printf("%c", tree_huffman[rt].c);
            rt = root;
    
        }
        printf("%s\n", ss);
    }
    

    完整code

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<string>
    #include<stdio.h>
    #include<stdlib.h>
    #include<cmath>
    using namespace std;
    
    typedef struct haffman
    {
        char c;///标记字符
        char flag[256]; ///标记哈夫曼编码
        double w;///标记权值
        int l, r;///左孩子有孩子
        int par;///标记是否存在父母节点
    }Tree;
    
    Tree tree_huffman[128]; ///ascii表共128个字符
    
    
    char *read_file(const char *filename)     ///从文件中读取字符串
    {
        FILE *fp = NULL;
        char buf[256];
        int len = 0;
        char *x = new char [10000];
        *x = '\0';
    
        if((fp = fopen(filename, "r"))==NULL)
        {
            perror("can't open the file");
            exit(1);
        }
        while(fgets(buf, 255, fp) != NULL)
        {
            len = strlen(buf);
            //printf("%d", len);
            if(buf[len-1] == '\n')
            {
                buf[len-1] = '\0';
            }
            //printf("%s\n", buf);
            strcat(x, buf);
        }
        //printf("%s\n", x);
        fclose(fp);
        return x;
    }
    
    int samechar(char *x)     ///该函数将不同字符出现的次数记录下来
    {
        int flag;
        int n=0;
        tree_huffman[n].c = x[0];
        tree_huffman[n].w = 1.0;
        int l=strlen(x);
        for(int i=1;i<l;i++)
        {
            int j;
            flag=0;
            for(j=0;j<=n;j++)
            {
                if(x[i]==tree_huffman[j].c)
                {
                    flag=1;
                    tree_huffman[j].w++;
                    break;
                }
            }
            if(!flag)
            {
                n++;
                tree_huffman[n].c=x[i];
                tree_huffman[n].w=1.0;
            }
        }
        return n+1;
    }
    
    int cmp(Tree a, Tree b)
    {
        return a.w<b.w;
    }
    
    int create_huffman(int n)   ///构建哈夫曼树
    {
        int rear = n, font = 0;
        Tree last;
        while(rear > font)
        {
            sort(tree_huffman+font, tree_huffman+rear, cmp);
            last = tree_huffman[font];
            last.l = font;
            font++;
            if (rear <= font)
                break;
            else
            {
                Tree t = tree_huffman[font];
                last.w += t.w;
                last.c = '\0';
                last.r = font;
                last.par = -1;
                font++;
                tree_huffman[rear++] = last;
            }
        }
        for(int i=0;i<rear;++i)
        {
            if(tree_huffman[i].l >= 0)
            {
                int lchild = tree_huffman[i].l;
                tree_huffman[lchild].par = i;
            }
            if(tree_huffman[i].r >= 0)
            {
                int rchild = tree_huffman[i].r;
                tree_huffman[rchild].par = i;
            }
        }
        //for(int i=0;i<rear;++i)
            //printf("%d, %c,%.2lf,%d,%d,%d\n", i, tree_huffman[i].c, tree_huffman[i].w, tree_huffman[i].l, tree_huffman[i].r, tree_huffman[i].par);
        return rear;
    
    }
    
    void output_tree_code(Tree &temp, char *code)
    {
        if(temp.l == -1 && temp.r == -1)
        {
            printf("%s\n", code);
            strcpy(temp.flag, code);
            return;
        }
        char t1[256], t2[256];
        strcpy(t1, code);
        strcpy(t2, code);
        output_tree_code(tree_huffman[temp.l], strcat(t1, "0"));
        output_tree_code(tree_huffman[temp.r], strcat(t2, "1"));
    }
    
    void wfile(const char *filename1, const char *filename2, int n)
    {
        FILE *fp = NULL;
        fp = fopen(filename2, "wb");
        char *buf = read_file(filename1);
        char *temp = new char [10000];
        temp[0] = '\0';
        for(int i=0;i<int(strlen(buf));++i)
        {
            for(int j=0;j<n;++j)
            {
                if(buf[i] == tree_huffman[j].c)
                {
                    //printf("%s\n", tree_huffman[j].flag);
                    strcat(temp, tree_huffman[j].flag);
                    //fwrite(tree_huffman[j].flag, (1.0/8.0)*strlen(tree_huffman[j].flag), 1, fp);
                    break;
                }
            }
        }
        printf("%s\n", temp);
        /*
        for(int i=0;i<8;++i)
        {
            int len = strlen(temp);
            if(len % 8 != 0)
            {
                strcat(temp, "0");
            }
            else
                break;
        }*/
        //printf("%s\n", temp);
        int len = 0;
        if(strlen(temp) % 8 == 0)
            len = strlen(temp) / 8;
        else
        {
            len = strlen(temp) / 8 + 1;
            while(strlen(temp) % 8 != 0)
            {
                strcat(temp, "0");
            }
        }
    
        for(int i=0;i<len;++i)
        {
            int a = 0;
            for(int j=0;j<8;++j)
            {
                int ca = temp[i*8+j] - '0';
                a += ca * pow(2, 7-j);
                //printf("%d\t", ca * pow(2, 8-j));
            }
            //printf("\n");
            //printf("%d\n", a);
            fwrite(&a, 1, 1, fp);
        }
        fclose(fp);
    }
    
    void unzip_huffman(const char *filename, int root)
    {
        FILE *fp = NULL;
        if((fp = fopen(filename, "rb"))==NULL)
        {
            perror("can't open the file");
            exit(1);
        }
        int cb[10000];
        int num = 0;
        while(!feof(fp))
        {
            int element = getc(fp);
            //printf("%d\t", element);
            if(element != -1)
            {
                for(int i=0;i<8;++i)
                {
                    int t = element % 2;
                    element = element / 2;
                    cb[num++] = t;
                }
            }
        }
        //printf("\n");
        //printf("cb:\n");
        //for(int i=0;i<num;++i)
            //printf("%d ", cb[i]);
        //printf("\n");
        int ccb[10000];
        int xnum = 0;
        for(int i=0;i<num/8;++i)
        {
            for(int j=0;j<8;++j)
            {
                ccb[xnum++] = cb[i*8+7-j];
            }
        }
        //for(int i=0;i<xnum;++i)
            //printf("%d ", ccb[i]);
        fclose(fp);
        char ss[10000] = "\0";
        int sr = 0;
        num = 0;
        int rt = root;
        while(num < xnum)
        {
            while(tree_huffman[rt].l != -1 && tree_huffman[rt].r != -1)
            {
                if(ccb[num] == 0)
                {
                    rt = tree_huffman[rt].l;
                }
                else if(ccb[num] == 1)
                {
                    rt = tree_huffman[rt].r;
                }
                num++;
            }
            ss[sr++] = tree_huffman[rt].c;
            //printf("%c", tree_huffman[rt].c);
            rt = root;
    
        }
        printf("%s\n", ss);
    }
    
    int main()
    {
    
        ios::sync_with_stdio(false);
        const char *filename = "doc1.txt";
        char *st = read_file(filename);
        printf("input file's reading:\n");
        printf("%s\n", st);
        int n = samechar(st);
        printf("the char kinds of %d\n", n);
        for(int i=0;i<n;++i)
        {
            //printf("%c", tree_huffman[i].c);
            tree_huffman[i].w /= strlen(st);
            tree_huffman[i].l = -1;
            tree_huffman[i].r = -1;
            tree_huffman[i].par = -1;
            memset(tree_huffman[i].flag, 0, sizeof(tree_huffman[i].flag));
            //printf("%.2lf\n", tree_huffman[i].w);
        }
        n = create_huffman(n);
        char code[256] = "\0";
        //printf("%d", n);
        output_tree_code(tree_huffman[n-1], code);
        for(int i=0;i<n;++i)
        {
            printf("%d, %c,%.2lf,%d,%d,%d, ", i, tree_huffman[i].c, tree_huffman[i].w, tree_huffman[i].l, tree_huffman[i].r, tree_huffman[i].par);
            printf("%s\n", tree_huffman[i].flag);
            //cout<<tree_huffman[i].flag<<endl;
        }
        wfile(filename, "2.huffman", n);
    
        unzip_huffman("2.huffman", n-1);
        return 0;
    }
    
    
    展开全文
  • 哈夫曼编码实现图像压缩,是自己整理的讲稿,希望对大家有用
  • AAAAABCD THE_CAT_IN_THE_HAT END 输出样例: 64 13 4.9 144 51 2.8 解题思路: 原题目贼长,不看也罢,单看输入描述和输出描述以及样例,再结合题目中的一点数字描述就知道是求一串字符串的哈夫曼编码压缩比。...

    题目描述:

    An entropy encoder is a data encoding method that achieves lossless data compression by encoding a message with "wasted" or "extra" information removed. In other words, entropy encoding removes information that was not necessary in the first place to accurately encode the message. A high degree of entropy implies a message with a great deal of wasted information; english text encoded in ASCII is an example of a message type that has very high entropy. Already compressed messages, such as JPEG graphics or ZIP archives, have very little entropy and do not benefit from further attempts at entropy encoding.

    English text encoded in ASCII has a high degree of entropy because all characters are encoded using the same number of bits, eight. It is a known fact that the letters E, L, N, R, S and T occur at a considerably higher frequency than do most other letters in english text. If a way could be found to encode just these letters with four bits, then the new encoding would be smaller, would contain all the original information, and would have less entropy. ASCII uses a fixed number of bits for a reason, however: it’s easy, since one is always dealing with a fixed number of bits to represent each possible glyph or character. How would an encoding scheme that used four bits for the above letters be able to distinguish between the four-bit codes and eight-bit codes? This seemingly difficult problem is solved using what is known as a "prefix-free variable-length" encoding.

    In such an encoding, any number of bits can be used to represent any glyph, and glyphs not present in the message are simply not encoded. However, in order to be able to recover the information, no bit pattern that encodes a glyph is allowed to be the prefix of any other encoding bit pattern. This allows the encoded bitstream to be read bit by bit, and whenever a set of bits is encountered that represents a glyph, that glyph can be decoded. If the prefix-free constraint was not enforced, then such a decoding would be impossible.

    Consider the text "AAAAABCD". Using ASCII, encoding this would require 64 bits. If, instead, we encode "A" with the bit pattern "00", "B" with "01", "C" with "10", and "D" with "11" then we can encode this text in only 16 bits; the resulting bit pattern would be "0000000000011011". This is still a fixed-length encoding, however; we’re using two bits per glyph instead of eight. Since the glyph "A" occurs with greater frequency, could we do better by encoding it with fewer bits? In fact we can, but in order to maintain a prefix-free encoding, some of the other bit patterns will become longer than two bits. An optimal encoding is to encode "A" with "0", "B" with "10", "C" with "110", and "D" with "111". (This is clearly not the only optimal encoding, as it is obvious that the encodings for B, C and D could be interchanged freely for any given encoding without increasing the size of the final encoded message.) Using this encoding, the message encodes in only 13 bits to "0000010110111", a compression ratio of 4.9 to 1 (that is, each bit in the final encoded message represents as much information as did 4.9 bits in the original encoding). Read through this bit pattern from left to right and you’ll see that the prefix-free encoding makes it simple to decode this into the original text even though the codes have varying bit lengths.

    As a second example, consider the text "THE CAT IN THE HAT". In this text, the letter "T" and the space character both occur with the highest frequency, so they will clearly have the shortest encoding bit patterns in an optimal encoding. The letters "C", "I’ and "N" only occur once, however, so they will have the longest codes.

    There are many possible sets of prefix-free variable-length bit patterns that would yield the optimal encoding, that is, that would allow the text to be encoded in the fewest number of bits. One such optimal encoding is to encode spaces with "00", "A" with "100", "C" with "1110", "E" with "1111", "H" with "110", "I" with "1010", "N" with "1011" and "T" with "01". The optimal encoding therefore requires only 51 bits compared to the 144 that would be necessary to encode the message with 8-bit ASCII encoding, a compression ratio of 2.8 to 1.

    输入:The input file will contain a list of text strings, one per line. The text strings will consist only of uppercase alphanumeric characters and underscores (which are used in place of spaces). The end of the input will be signalled by a line containing only the word “END” as the text string. This line should not be processed.

    输出:For each text string in the input, output the length in bits of the 8-bit ASCII encoding, the length in bits of an optimal prefix-free variable-length encoding, and the compression ratio accurate to one decimal point.

    输入样例:

    AAAAABCD
    THE_CAT_IN_THE_HAT
    END

    输出样例:

    64 13 4.9
    144 51 2.8

    解题思路:

            原题目贼长,不看也罢,单看输入描述和输出描述以及样例,再结合题目中的一点数字描述就知道是求一串字符串的哈夫曼编码压缩比。首先要根据输入的字符串,统计出现过的字符,以及频率。之后按照字符的频率作为权值做最小带权路径和也就是整个字符串采用哈夫曼编码的总长度。最后用8位*字符串长度除以哈夫曼编码长度,计算出压缩比。

    解题步骤:

            1、使用数组统计输入字符串中每个字符出现过的次数;

            2、每个出现过的字符的出现次数作为权值,放入一个优先级队列中,采用升序排序;

            3、考虑边界情况,若整个字符串中只有同一个字符,没法生成新结点,单独处理;

            4、按照新生成结点的权值和 = 每个叶子的带权路径长度 = 字符串采用哈夫曼编码的位数;求出该字符串长度,再做除法运算,求出压缩比。

    代码实现:

    #include <iostream>
    using namespace std;
    #include <queue>
    
    int freq_arr[27];
    string s;
    
    int main()
    {
      
        while (cin >> s && s != "END")
        {
            int total = 0;
            int sum = 0;
            priority_queue<int, vector<int>, greater<int> > q;
            memset(freq_arr, 0, sizeof(freq_arr));
            int n = s.size();
            for (int i = 0; i < n; i++)
            {
                if (s[i] == '_')
                {
                    freq_arr[26]++;
                }
                else
                {
                    freq_arr[s[i] - 'A']++;
                }
            }
            for (int i = 0; i < 27; i++)
            {
                if (freq_arr[i])
                {
                    q.push(freq_arr[i]);
                }
            }
            if (q.size() == 1)
            {
                total = q.top();
                printf("%d %d %.1lf\n", n * 8, n * 1, (double)8/1);
            }
            else
            {
                while (q.size() > 1)
                {
                    sum = 0;
                    sum += q.top();
                    q.pop();
                    sum += q.top();
                    q.pop();
                    q.push(sum);
                    total += sum;
                }
                printf("%d %d %.1lf\n", n * 8, total, (double)n * 8 / total);
            }
        }
    
        return 0;
    }

    展开全文
  • 参考Crash Course的课程,做下笔记,原视频在这里 ↓ ... 我们要对如下一张 4像素 X 4像素的 图片进行压缩, 而在磁盘中图片是一串像素值的形式...为了能够压缩图片,我们需要减少冗余的信息或者用更紧凑的表示方...

    参考Crash Course的课程,做下笔记,原视频在这里 ↓

    https://www.bilibili.com/video/BV1EW411u7th?p=21

    1. 我们要对如下一张 4像素 X 4像素的 图片进行压缩,
      在这里插入图片描述
      而在磁盘中图片是一串像素值的形式存储的,每个像素的颜色由RGB确定,这样一张图片需要 48(16*3) 个字节
      在这里插入图片描述
    2. 为了能够压缩图片,我们需要减少冗余的信息或者用更紧凑的表示方法。可以发现,有很多相同的排列:白黄、黑黄、黄黄、白白,这个序列可以有这四种排列组成(当然也有其他不同的方式),我们为这四种排列生成紧凑代码,用更少的字节表示每对排列

    在这里插入图片描述

    1. 我们会发现,这四对出现的频率并不相同
      在这里插入图片描述
      黄黄出现的次数最多,所以我们希望通过最紧凑的方式来表示,其次是白黄,黑黄和白白出现的次数最少,我们可以用长一点的来表示

    2. 为了实现以上的表示,我们需要构造哈夫曼树

      • 列出所有的块和频率,每轮选择两个最低的频率,将它们组成一个树。这里BY和WW频率最低,将其组成一个树,组成后的频率为2,这样就完成了一轮算法。
        在这里插入图片描述
      1. 下一轮中重复这样的操作。现在白色的两个频率最低,合并!
        在这里插入图片描述
        合并之后的情况如下
        在这里插入图片描述
      2. 第三轮同理
        在这里插入图片描述
        这样我们就完成了哈夫曼树,它是按照频率排序的,频率低的在下面,频率高的在上
    3. 完成了哈夫曼树,我们还需要生成字典,即如何访问各个节点。我们可以将所有的左子树的分支用0标示,右子树用1标示
      在这里插入图片描述
      这样我们就完成了字典
      在这里插入图片描述
      这样我们可以用0 标示YY,111标示 WW…
      经过这样的压缩后,原本的字符可以表示为如下的形式
      在这里插入图片描述
      这样原来的48字节我们用14位就能表示了!!! (48字节=48 X 8位 = 384 位)

    4. 当然,只保存14位的数据是没有意义的,我们需要将字典也保存下来才能知道表示的信息
      在这里插入图片描述
      加上字典信息后我们需要30字节的空间,仍然比48字节好很多。

    展开全文
  • 哈夫曼编码压缩图像

    千次阅读 2020-06-15 10:09:47
    loc:第一次排序时是i,因为哈夫曼编码先将概率从大到小排序;当不是第一次时,就是上一次排序的位置 find(S(j,:)==loc):S保存的是每次排序前的位置,所以这一命令可以找到排序后,即当前该概率值ai的位置 find(S...

    最近在学相关的东西,本来是编辑好了贴代码就行了,但由于新手操作,一放代码就出问题导致心态崩了。所以就不讲原理了,试试看代码怎么放吧。枯了。

    原理就看下图吧。(感觉变糊了)
    在这里插入图片描述

    代码思路大概就是,我认为只有出现在最后两位最小的概率值需要加码字0或者1。所以就可以正向直接求每一个概率值的码字。比如说第一个概率a1,排序后判断是否是最后一个,是的话就加一个码字0;如果是倒数第二个,就加码字1;如果两种情况都不是,就保持码字不变。

    值得注意的是代码中出现的(find(S(j,:)==loc)==L)、(find(S(j,:)==loc)==L-1)其实是想要找到当前求的概率的位置,其实就是想要实现(find(ai)==L-1)。但是由于每次最后两个概率相加之后都要重新排序,所以a1的位置不可能总是在第一个(即ai不可能总是在第i个),所以每次排序都要记下排序前ai的位置loc(第一次排序的位置就是i),然后根据这个loc来判断下一次排序后ai的位置是否在最后两个。

    loc:第一次排序时是i,因为哈夫曼编码先将概率从大到小排序;当不是第一次时,就是上一次排序的位置

    find(S(j,:)==loc):S保存的是每次排序前的位置,所以这一命令可以找到排序后,即当前该概率值ai的位置

    find(S(j,:)==loc)==L:判断是否在最后一个

    下面就是写的代码(尝试了几次,不知道怎么办我就只能贴图了):

    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • 基于哈夫曼编码的文本文件压缩与解压缩,使用c语言,实际只是编码解码,不应该称为解压缩,因为编码后文件会更大
  • 5.对应哈夫曼编码生成新的bytes,并将bytes和哈夫曼编码一同输出到压缩文件中 解压: 1.先读取数据和哈夫曼编码 2.反转哈夫曼编码(key,value互换) 3.对应反转后的哈夫曼编码恢复原来文件 3.输出恢复好的文件 注意...
  • 数据结构大作业——哈夫曼编码压缩BMP格式文件

    千次阅读 多人点赞 2020-04-17 10:21:06
    数据结构大作业——哈夫曼编码压缩BMP格式文件 首先需要了解BMP图像格式 BMP图像格式详解 其次需要了解哈夫曼编码如何对BMP文件进行压缩 哈夫曼压缩与解压缩 编程部分 从BMP文件中读取需要的内容 首先是自定义图像...
  • 最新版本 实现了代码的优化 运行效率的提升 还新增了用户界面 代码内附注释 可压缩任何类型的文件 100%解压
  • 利用哈夫曼编码思想,设计对一个文本文件(.txt)中的字符进行哈夫曼编码,生成编码压缩文件(.txt),并且还可将压缩后的文件进行解码还原为原始文本文件(.txt)。 实现的功能: (1)压缩:实现对文件的压缩,生成...
  • 专业实践,使用哈夫曼编码进行压缩解压
  • bupt数据结构实验,哈夫曼编码实现任意文件类型压缩,原创内容,代码仅供各位学习参考,严禁抄袭等学术不端行为
  • C++实现哈夫曼编码

    2020-08-19 06:23:38
    主要为大家详细介绍了C++实现哈夫曼编码,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 通过哈夫曼编码压缩文件

    千次阅读 2018-10-11 15:04:06
    原理就是统计带压缩文件字符频率,构建哈夫曼树,然后求哈夫曼编码,将字符频率(解压的时候通过字符频率建树)和哈夫曼编码写入文件,完成压缩压缩代码: //获取一个文件的每个字符的频率 void get_frequency...
  • 本文采用哈夫曼编码的方式进行文件(文本文件)压缩和解压缩,首先介绍项目的整体思路:哈夫曼编码压缩文件实际就是统计出文件中各个字符出现的频率,然后为每个字符生成对应的编码,然后将每个字符用哈夫曼编码的...
  • 利用哈夫曼编码压缩文件

    千次阅读 2017-09-05 17:54:48
    本大作业主要考核如何以C实现集成电路测试向量文件的无损压缩。在通常的文件存储中,无论是二进制格式的文件还是文本文件,几乎都是等宽的编码。比如ASCII码格式的文本文件,每个字符由一个ASCII码表示,宽度为8bit...
  • 哈夫曼编码压缩文件

    2012-07-09 02:57:00
    用Java实现,哈夫曼编码实现文件压缩,有详细注释
  • 压缩压缩后 经验证解压缩前与解压缩后文本一致,无出入 文件目录 binaryTreeNode.h linkedBinaryTree.h 源.cpp 代码如下 binaryTreeNode.h #ifndef binaryTreeNode_ #define binaryTreeNode_ #include #...
  • 利用无失真信源编码方法中的哈夫曼编码进行程序设计实践,实现对文件的压缩与解压操作。
  • 压缩过程就是编码过程,解压缩过程就是解码过程。压缩技术分为无损压缩和有损压缩两大类,前者在解码时可以精确地恢复原图像,没有任何损失;后者在解码时只能近似原图像,不能无失真地恢复原图像。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 8,041
精华内容 3,216
关键字:

哈夫曼编码压缩