精华内容
下载资源
问答
  • 哈夫曼编码算法实现

    2014-12-21 17:53:27
    哈夫曼编码算法实现 C实现 实验说明实现文档
  • Matlab的卷积编码实现

    千次阅读 2020-03-24 22:10:57
    最近在做一个SCFDE波形的C和矢量实现,指导老师给了几份Matlab仿真代码,要我把对应的C语言和矢量写出来(并行运算指令操作),简单的代码一下就写完了,有些写的还是有点烦躁,特别是卷积编码的解码,今天我们先不谈...

    最近在做一个SCFDE波形的C和矢量实现,指导老师给了几份Matlab仿真代码,要我把对应的C语言和矢量写出来(并行运算指令操作),简单的代码一下就写完了,有些写的还是有点烦躁,特别是卷积编码的解码,今天我们先不谈解码,先谈下编码,这个还是写的比较流畅的。
    卷积编码器,听着就不好理解,没事,我来分析一波,首先我们来分析下(3,1,2)编码器,这三个数啥意思啊,3代表有三个输出,1代表一个输入,而约束度为N=2+1=3;这是啥意思呢,简单的来说就是一个输入进去,有三个输出,而约束度是为了在纠错时用的,也就是其能够监督3个信息段(每次一个比特输入的话,也就是能监督9个比特);下面我们来分析其实际应用:
    在matlab我们适用卷积编码函数时,是不是得调用一个网格函数?就是这个trel = poly2trellis(ConstraintLength,CodeGenerator);
    简单的来说,ConstraintLength是有几个移位寄存,CodeGenerator是代表有几路输出以及输出与移位寄存器的关系,
    设trel = poly2trellis(7,[171,133]);这里代表有7个寄存器,两路输出,171和133是啥啊,在这里171和133是八进制,要转换为二进制才能知道他们的关系:[1111001,1011011];这是不是很清楚了(如图1),它们是异或运算,也就是,第一个输出是1、2、3、4、7寄存器的值的异或。
    图一
    第一个输出与1、2、3、4、7这几个寄存器有关系,那么trel = poly2trellis(7,[171,133]),convenc_out = convenc(x(n),trel)是不是就代表(2,1,6)编码器呢?那么(3,1,2)编码器同理,这不过这样说明,没有指定输出与寄存器的关系,下面看一段我实现的代码(如图2、图3):
    图二
    图三
    下面验证一下结果(如图4):
    在这里插入图片描述
    如果有什么问题我们还可以再讨论一下。

    展开全文
  • 哈夫曼编码实现

    万次阅读 多人点赞 2018-12-18 22:01:06
    哈夫曼编码是一种结合二叉树与贪心算法的文字、数据编码方式。具有较广的应用背景,最直观的应用便是文件压缩。举例说明,有一串多个字符组成的字符串“abbcccddddeeeee”,该字符串包含有五个字符,abcde五个字符...

    前言  

    哈夫曼编码是一种结合二叉树与贪心算法的文字、数据编码方式。具有较广的应用背景,最直观的应用便是文件压缩。举例说明,有一串多个字符组成的字符串“abbcccddddeeeee”,该字符串包含有五个字符,abcde五个字符分别出现的次数为1,2,3,4,5.。由于一个字符需要由多个二进制位进行表示,为了不混淆字符,需要用3个二进制位来表示字符才可以确保5种不同的组合(2^{3}=8>5),这串字符一共需要3*15=45位来表示。将信息一个不落地表示需要满足每一个单元信息的互异性,同时也要按原有的顺序来将信息写出。而这串信息中每个字符的哈夫曼对应为 a-010 b-011 c -00 d-10 e-11,此时的字符串需3*1+3*2+2*3+2*4+2*5=33位来表示。通过将高频率字符用较短字节进行表示而不是统一表示的方法达到字符串的压缩。

     

    正文

    1.哈夫曼编码的概念

    哈夫曼树又称作最优树,是一种带权路径长度最短的树,而通过哈夫曼树构造出的编码方式称作哈夫曼编码。先补充以下三个概念:

    1)路径长度

    二叉树中一个结点到另一个结点经过的结点方式是唯一的,这些经过的结点称作两个结点之间的路径。而由结点A到结点B中间经历的结点数目加1即为结点A到B的路径长度

    2)结点权值

    图当中,每一个结点代表着不同的数字,而这些不同的数字称作结点的权值。

    3)带权路径长度

    假设同样的例子,由结点A到结点B的过程中,经过的路径长度为3,结点B的权值为4。则3*4=12称作结点的带权路径长度。到结点的带权路径长度计算方式为路径长度乘结点的权值。而树的带权路径长度,意为树的根结点到所有的叶子结点的带权路径长度之和。表达公式如下:

                                                      WPL=\sum_{i=1}^{n}w_{i}*l_{i}                      

    WPL代表树的带权路径长度,w_{i}代表树叶子结点的权值,l_{k}代表根结点到每个叶子结点的路径长度。

    哈夫曼树必须要求WPL达到最短,而哈夫曼编码的编写方式,则要求将所有需要编码的元素放置在哈夫曼树的叶子结点上,方便编码。

    2.哈夫曼编码的构造方法

    哈夫曼编码在编写的过程中,要求先构造哈夫曼树。遵照的是权值最小原则,以前言中提到的字符串为例,字符 a的权值赋值为1,字符b的权值赋值为2,c的权值赋值为3,d的权值赋值为4,e的权值赋值为5。

    1)选取权值最小的两个点1 2,将两个点作为叶子结点。1作为左孩子,2作为右孩子构造一棵新二叉树,根结点的权值为两叶子结点之和3。

    2)将新的根结点作为叶子结点考虑,比较权值为{3,3,4,5}的四个结点,得出权值最小的为3和3。与第一步类似,以这两个点作为叶子结点,构造一棵新二叉树,根结点的权值为两叶子结点之和6。

    3)此时集合为{4,5,6}三个结点,此处集合权值最小的两个点为 4 5,则将4,5作为叶子结点。4作为左孩子,5作为右孩子构造一棵新的二叉树,根结点权值为9

    4)最后集合为{6,9},将两个点合并为一棵二叉树。6作为左孩子,9作为右孩子,根结点为15。

     构造哈夫曼树的情况如下:

    案例哈夫曼树的构造

    构造完毕哈夫曼树后,由根结点开始对叶子结点进行编码,要求根结点的左子树添加的数字为0,右子树添加的数字为1,将左右子树分别作为根结点继续向下添加编码。一直添加数字到每个叶子结点为止。叶子结点对应的数字是这个叶子元素的哈夫曼编码。编码结果为: a-010 b-011 c -00 d-10 e-11,哈夫曼编码的过程如下:

    案例的哈夫曼编码

    3.哈夫曼编码构造的代码实现

    在了解了哈夫曼编码的原理后,需要开始进行哈夫曼编码的实现,实现过程中主要有三个难点,其一是二叉树的构造,其二是最小值的挑选,其三是一维的数组如何转换为二叉树的结构。可以对节点进行编号,用编号来访问具有父子关系的结点。基本思路如下:

    1)分析哈夫曼树的结构以及结点数目关系

    假设哈夫曼树具有m个结点,叶子结点的数目为n,则不难得出 m=2*n-1 。建立一个哈夫曼树类的结点,其中类的变量包括权值weight,左孩子的下标lchild,右孩子的下标rchild,父结点的下标parent,类的一个构造函数记作HTNode(int w,int p,int l,int r)。用于进行哈夫曼树结点的初始化以及赋值。同链表的想法类似,类的单个对象记作HTnode,定义一个类的指针对象HuffmanTree.

    类的代码如下:

    #include <iostream>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    using namespace std;
    
    typedef struct HTNode
    {
        int weight;
        int parent;
        int lchild;
        int rchild;
        HTNode(int w,int p,int l,int r):weight(w),parent(p),lchild(l),rchild(r){}
    }HTnode,*HuffmanTree;

    2)函数基本结构的实现

    定义一个哈夫曼编码加密函数Huffmancoding(),其中函数的自变量包括HuffmanTree类型的对象数组HT,定义一个二维的字符指针Huffmancode,Huffmancode的对象名称记作HC。分成多行,用于存储abcde五个待编码的字符,每一个字符都对应的编码均存储在Huffmancode的每一行中。定义一个int型指针,记作w,w指向的数组用于存储每一个字符的权值。最后需要定义变量n,记录下叶子结点的数目,同时根据叶子结点的数目也可以推断出包括根结点在内的所有结点的数目。函数声明如下:

    typedef char**Huffmancode;
    void Huffmancode(HuffmanTree &HT,Huffmancode &HC,int *w,int n);

    在定义完成该输入的变量后,定义int类型的变量记作m与i。m代表结点的数目,同时也控制着HT对象内存的分配,i控制着循环。对于下标为1到n的结点,控制它们承担叶子结点的信息,相应地,初始化时将结点的权值与w中的各个数字相互对应,父子结点以及左右孩子的信息均初始化为0。对于下标n+1到m的结点,初始化值均设为0。HT对象内存分配以及叶子结点初始化代码如下:

    m=n*2-1;
    HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
    for(i=1;i<=n;i++,w++)
    {
        HT[i]=HTNode(*w,0,0,0);
    }
    for(;i<=m;i++)
    {
        HT[i]=HTNode(0,0,0,0);
    }

    在结点初始化完成后,需要完善的是对应父子结点的信息,对于不同下标的结点进行结点内部元素的赋值,达到构建二叉树的效果。

    假设存在一个待实现的Select函数,找到权值最小的两个点的下标,实现放到3)实现Select函数来讲,两个权值最小的结点下标为child1,child2。通过for循环,i 的值初始化为n+1,最后到达m为止,i 每一次都增加1。将HT[i]作为HT[child1]与HT[child2]的父亲结点,将对应的权值以及左右孩子值均赋上。通过for循环中存在的 i+1操作将新产生的HT[i]结点加入待寻找权值最小的序列中。实现代码如下:

    for(i=n+1;i<=m;i++)
    {
        Select(HT,i-1,child1,child2);  //i-1=n时代表前n个结点中找权值最小的两个点,i++使得i=n+1
        HT[child1].parent=i;           //时的新产生的父结点被包括进来
        HT[child2].parent=i;
        HT[i].lchild=child1;
        HT[i].rchild=child2;
        HT[i].weight=HT[child1].weight+HT[child2].weight;
    }
    

    寻找了权值最小的两个结点HT[child1],HT[child2]后,需要开始对待编码的字符进行编码。这里主要是运用了向上回溯的思想,通过对每个叶子结点的访问来达到编码的效果。给HC分配空间,定义字符指针cd,用来存储每一个字母对应的编码值。按照访问叶子结点的思路,先通过外层for循环来访问每一个叶子结点。访问叶子结点后,通过内层for循环向上回溯,添加内外for循环的语句如下:

    void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int *w,int n)
    {
        int m,i;
        int child1,child2;
        if(n<=1)
        {
            return;
        }
        m=n*2-1;
        HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
        for(i=1;i<=n;i++,w++)
        {
            HT[i]=HTNode(*w,0,0,0);
        }
        for(;i<=m;i++)
        {
            HT[i]=HTNode(0,0,0,0);
        }
        for(i=n+1;i<=m;i++)
        {
            Select(HT,i-1,child1,child2);
            HT[child1].parent=i;
            HT[child2].parent=i;
            HT[i].lchild=child1;
            HT[i].rchild=child2;
            HT[i].weight=HT[child1].weight+HT[child2].weight;
        }
        HC=(char**)malloc((n+1)*sizeof(char*));
        char*cd=(char*)malloc(n*sizeof(char));
        int temp,count;
        for(i=1;i<=n;i++)
        {
            count=0;
            for(int c=i,temp=HT[i].parent;temp!=0;c=temp,temp=HT[temp].parent)
            {
                if(HT[temp].lchild==c)
                {
                    cd[count++]='0';
                }
                else
                {
                    cd[count++]='1';
                }
            }
            cd[count]='\0';
        }
    }
    

    其中c代表当前访问结点的下标,temp代表该结点父结点的下标,若当前结点是它父结点的左孩子,则在cd中添加上字符 ‘0’,若是右孩子,则在cd中添加上字符 ‘1’。每经过一次叶子结点的编码后cd均会更新。需要注意的是,将cd写入HC的每一行中时,需要将cd反向写入(由叶子结点向上回溯得到的编码是相反的),完整编码的代码如下:

    void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int *w,int n)
    {
        int m,i;
        int child1,child2;
        if(n<=1)
        {
            return;
        }
        m=n*2-1;
        HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
        for(i=1;i<=n;i++,w++)
        {
            HT[i]=HTNode(*w,0,0,0);
        }
        for(;i<=m;i++)
        {
            HT[i]=HTNode(0,0,0,0);
        }
        for(i=n+1;i<=m;i++)
        {
            Select(HT,i-1,child1,child2);
            HT[child1].parent=i;
            HT[child2].parent=i;
            HT[i].lchild=child1;
            HT[i].rchild=child2;
            HT[i].weight=HT[child1].weight+HT[child2].weight;
            cout<<child1<<" "<<child2<<endl;
        }
        HC=(char**)malloc((n+1)*sizeof(char*));
        char*cd=(char*)malloc(n*sizeof(char));
        int temp,count;
        for(i=1;i<=n;i++)
        {
            count=0;
            for(int c=i,temp=HT[i].parent;temp!=0;c=temp,temp=HT[temp].parent)
            {
                if(HT[temp].lchild==c)
                {
                    cd[count++]='0';
                }
                else
                {
                    cd[count++]='1';
                }
            }
            cd[count]='\0';
            HC[i]=(char*)malloc((count)*sizeof(char));
            for(int j=count;j>=0;j--)
            {
                HC[i][count-j]=cd[j-1];//cd反向输入
            }
        }
    }
    

    3)实现Select函数

          按已经实现的想法来看,需要完成一个函数以对权值最小的两个结点进行合并,用一个函数Select完成对这两个权值最小结点的寻找,在其他函数中再对其进行实现。进行Select函数的函数自变量包括哈夫曼树对象HT,待寻找的结点集合下标最大值Num,以及两个权值最小的结点的下标child1,child2。经过此函数的目的,是将寻找到正确的child1与child2的值,使得在该次循环中HT[child1]与HT[child2]的权值达到最小。

         基本思路如下:1.判断HT[i].parent是否为0,若不为0,则代表这个结点已经被归入一棵树内,不能再次进行合并,为0则可以继续  2.child1,child2,w1,w2均初始化为0  3.通过(w1>w2)或(w2>w1)在 i 从 1 至Num中反复找最小权值的两个点,在多次的循环中child1与child2会反复更新,并且(w2>w1)条件在后保证了HT[child1]的权值要小于HT[child2]的权值。代码如下:

    void Select(HuffmanTree &HT,int num,int &child1,int &child2)
    {
        child1=0;
        child2=0;
        int w1=0;
        int w2=0;
        for(int i=1;i<=num;i++)
        {
            if(HT[i].parent==0)
            {
                if(child1==0)
                {
                    child1=i;
                    w1=HT[i].weight;
                    continue;
                }
                if(child2==0)
                {
                    child2=i;
                    w2=HT[i].weight;
                    continue;
                }
                if(w1>w2&&w1>HT[i].weight)
                {
                    w1=HT[i].weight;
                    child1=i;
                    continue;
                }
                if(w2>w1&&w2>HT[i].weight)
                {
                    w2=HT[i].weight;
                    child2=i;
                    continue;
                }
            }
        }
    }

    4)主函数的实现

    相对以上步骤,主函数便极其容易,这里直接将 abcde 五个字符的权值存在数组中,直接输出了每个字符的编码,主程序如下:

    
    int main()
    {
        char a[]={'a','b','c','d','e'};
        int b[]={1,2,3,4,5};
        HuffmanTree HT;
        HuffmanCode HC;
        HuffmanCoding(HT,HC,b,5);
        for(int j=1;j<=5;j++)
        {
            cout<<a[j-1]<<" "<<HC[j]<<endl;
        }
        return 0;
    }
    

    编码结果如下所示:

    #include <iostream>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    using namespace std;
    
    typedef struct HTNode
    {
        int weight;
        int parent;
        int lchild;
        int rchild;
        HTNode(int w,int p,int l,int r):weight(w),parent(p),lchild(l),rchild(r){}
    }HTnode,*HuffmanTree;
    
    typedef char** HuffmanCode;
    
    void Select(HuffmanTree &HT,int num,int &child1,int &child2)
    {
        child1=0;
        child2=0;
        int w1=0;
        int w2=0;
        for(int i=1;i<=num;i++)
        {
            if(HT[i].parent==0)
            {
                if(child1==0)
                {
                    child1=i;
                    w1=HT[i].weight;
                    continue;
                }
                if(child2==0)
                {
                    child2=i;
                    w2=HT[i].weight;
                    continue;
                }
                if(w1>w2&&w1>HT[i].weight)
                {
                    w1=HT[i].weight;
                    child1=i;
                    continue;
                }
                if(w2>w1&&w2>HT[i].weight)
                {
                    w2=HT[i].weight;
                    child2=i;
                    continue;
                }
            }
        }
    }
    
    
    //HuffmanCode是一个二维数组,用于存储字符
    //HuffmanTree是一棵哈夫曼树
    void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int *w,int n)
    {
        int m,i;
        int child1,child2;
        if(n<=1)
        {
            return;
        }
        m=n*2-1;
        HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
        for(i=1;i<=n;i++,w++)
        {
            HT[i]=HTNode(*w,0,0,0);
        }
        for(;i<=m;i++)
        {
            HT[i]=HTNode(0,0,0,0);
        }
        for(i=n+1;i<=m;i++)
        {
            Select(HT,i-1,child1,child2);
            HT[child1].parent=i;
            HT[child2].parent=i;
            HT[i].lchild=child1;
            HT[i].rchild=child2;
            HT[i].weight=HT[child1].weight+HT[child2].weight;
            //cout<<child1<<" "<<child2<<endl;
        }
    
        HC=(char**)malloc((n+1)*sizeof(char*));
    
        char*cd=(char*)malloc(n*sizeof(char));
    
    
        int temp,count;
        for(i=1;i<=n;i++)
        {
            count=0;
            for(int c=i,temp=HT[i].parent;temp!=0;c=temp,temp=HT[temp].parent)
            {
                if(HT[temp].lchild==c)
                {
                    cd[count++]='0';
                }
                else
                {
                    cd[count++]='1';
                }
            }
            cd[count]='\0';
            //cout<<cd<<" "<<i<<endl;
            HC[i]=(char*)malloc((count)*sizeof(char));
            for(int j=count;j>=0;j--)
            {
                HC[i][count-j]=cd[j-1];
            }
        }
    }
    
    
    int main()
    {
        char a[]="abbcccddddeeeee";
        char c[]={'a','b','c','d','e'};
        int i=strlen(a);
        int b[]={1,2,3,4,5};
        HuffmanTree HT;
        HuffmanCode HC;
        HuffmanCoding(HT,HC,b,5);
        for(int j=1;j<=5;j++)
        {
            cout<<c[j-1]<<" "<<HC[j]<<endl;//此处似乎是用来进行字符的编码的?输出abcd四个字符所对应的编码
        }
        return 0;
    }
    

     

    展开全文
  • 循环码编码译码的Matlab实现

    热门讨论 2010-05-27 11:27:22
    利用Matlab实现循环码的编码与译码 里面有WORD文档说明编译码的实现方式
  • Huffman编码的C语言实现

    千次阅读 2017-04-19 22:12:30
    Huffman 编码(1) Huffman Coding (霍夫曼编码)是一种无失真编码编码方式,Huffman 编码是可变字长编码(VLC)的一种。...(3)在程序实现中常使用一种叫做树的数据结构实现 Huffman 编码,由它编出的码是即时

    实验原理

    Huffman 编码

    (1) Huffman Coding (霍夫曼编码)是一种无失真编码的编码方式,Huffman 编码是可变字长编码(VLC)的一种。
    (2)Huffman 编码基于信源的概率统计模型,它的基本思路是,出现概率大的信源符号编长码,出现概率小的信源符号编短码,从而使平均码长最小。
    (3)在程序实现中常使用一种叫做树的数据结构实现 Huffman 编码,由它编出的码是即时码。

    Huffman编码的数据结构

    typedef struct huffman_node_tag
    {
        unsigned char isLeaf;//是否为树叶
        unsigned long count;//节点代表的符号加权和
        struct huffman_node_tag *parent;//父节点指针
    
        union//共同体:如果是叶节点,则只能有symbol,如果是非叶节点,只能有左右孩子指针
        {
            struct
            {
                struct huffman_node_tag *zero, *one;//左右孩子指针
            };
            unsigned char symbol;//符号,叶节点带有的字符
        };
    } huffman_node;
    typedef struct huffman_code_tag
    {
        /*以比特为单位的代码的长度。 */
        unsigned long numbits;
        /* The bits that make up this code. The first
           bit is at position 0 in bits[0]. The second
           bit is at position 1 in bits[0]. The eighth
           bit is at position 7 in bits[0]. The ninth
           bit is at position 0 in bits[1]. */
        unsigned char *bits;//指向该码比特串的指针
    
    } huffman_code;

    Huffman 编码的方法

    (1)统计符号的发生概率
    (2)把频率按从小到大的顺序排列
    (3)每一次选出最小的两个值,作为二叉树的两个叶子节点,将和作为它们的根节点, 这两个叶子节点不再参与比较,新的根节点参与比较
    (4) 重复 3,直到最后得到和为 1 的根节点
    (5) 将形成的二叉树的左节点标 0,右节点标 1,把从最上面的根节点到最下面的叶 子节点途中遇到的 0,1 序列串起来,就得到了各个符号的编码。

    实验流程

    这里写图片描述

    重要代码分析

    读入待编码的源文件

    int
    main(int argc, char** argv)//argc命令行参数个数和argv命令行参数
    {
        char memory = 0;//memory为0时,为文件的编解码,memory为1时为内存的编解码
        char compress = 1;//compress为1时为编码,为0时为解码
        int opt;//getopt()的返回值 
        const char *file_in = NULL, *file_out = NULL;//输入输出文件名
        //step1:add by yzhang for huffman statistics
        const char *file_out_table = NULL;
        //end by yzhang
        FILE *in = stdin;
        FILE *out = stdout;
        //step1:add by yzhang for huffman statistics
        FILE * outTable = NULL;//用于txt文件的输出
        //end by yzhang
    
        /* 获取命令行参数 */
        while((opt = getopt(argc, argv, "i:o:cdhvm")) != -1)//opt的返回值为iocdhvm或-1,getopt处理以'-’开头的命令行参数
        {
            switch(opt)
            {
            case 'i'://输入文件
                file_in = optarg;//optarg为选项参数缩写,该变量存放参数
                break;
            case 'o'://输出文件
                file_out = optarg;
                break;
            case 'c'://压缩
                compress = 1;
                break;
            case 'd'://解压缩
                compress = 0;
                break;
            case 'h'://帮助显示使用方法
                usage(stdout);
                return 0;
            case 'v'://输出版本版权信息
                version(stdout);
                return 0;
            case 'm':
                memory = 1; //memory为1时为内存的编解码
                break;
            // by yzhang for huffman statistics
            case 't':
                file_out_table = optarg;            
                break;
            //end by yzhang
            default:
                usage(stderr); //如果是其他情况,则将使用方法信息送到标准错误文件
                return 1;
            }
        }

    getopt()函数是Linux和Unix系统环境下解析命令行的函数。在本次实验中,命令行可设置为“-i test1.doc -o test1.huff -c -t test1.txt”

    Huffman文件编码时的总流程

    #define MAX_SYMBOLS 256
    typedef huffman_node* SymbolFrequencies[MAX_SYMBOLS];//表示信源符号的数组
    typedef huffman_code* SymbolEncoder[MAX_SYMBOLS];//表示码字的数组,用于保存码表

    Huffman文件编码的函数

    int
    huffman_encode_file(FILE *in, FILE *out, FILE *out_Table)//step1:changed by yzhang for huffman statistics from (FILE *in, FILE *out) to (FILE *in, FILE *out, FILE *out_Table)表示输出文件结果的指针
    {
        SymbolFrequencies sf;//
        SymbolEncoder *se;
        huffman_node *root = NULL;
        int rc;
        unsigned int symbol_count;
        //step2:add by yzhang for huffman statistics
        huffman_stat hs;
        //end by yzhang
    
    /*第一次扫描,得到输入文件每个信源符号出现的频率*/
        symbol_count = get_symbol_frequencies(&sf, in); //演示扫描完一遍文件后,SF指针数组的每个元素的构成
    
        //step3:add by yzhang for huffman statistics,...  get the frequency of each symbol 
        huffST_getSymFrequencies(&sf,&hs,symbol_count);
        //end by yzhang
    
        /*从symbolCount构建最佳表。即构建霍夫曼树 */
        se = calculate_huffman_codes(&sf);
        root = sf[0];
    
        //step3:add by yzhang for huffman statistics... output the statistics to file
        huffST_getcodeword(se, &hs);
        output_huffman_statistics(&hs,out_Table);
        //end by yzhang
    
        /*再次扫描文件,并使用之前构建的表将其编码到输出文件中。 */
        rewind(in);
        rc = write_code_table(out, se, symbol_count);//在输出文件中写入码表
        if(rc == 0)
            rc = do_file_encode(in, out, se);//第二次扫描,写完码表后对文件字节按照码表进行编码
    
        /* 释放霍夫曼树 */
        free_huffman_tree(root);
        free_encoder(se);
        return rc;
    }

    第一次扫描,统计文件中各个字符出现频率

    1.创建一个256元素的指针数组,用以保存256个信源符号的频率,其下标对应相应字符的ASCAII码。
    2.数组中的非空元素为当前编码文件中实际出现的信源符号

    static unsigned int
    get_symbol_frequencies(SymbolFrequencies *pSF, FILE *in)//统计文件中各个字符出现频率
    {
        int c;
        unsigned int total_count = 0;//扫描的总信源符号数,初始化为0
    
        /* 将所有信源符号地址初始化为NULL,使得所有字符频率为0 */
        init_frequencies(pSF);
    
        /* 计算输入文件中每个符号的频率。 */
        while((c = fgetc(in)) != EOF)//挨个读取字符
        {
            unsigned char uc = c;//将读取的字符赋给uc
            if(!(*pSF)[uc])//如果uc不存在对应的空间,即uc是一个新的符号
                (*pSF)[uc] = new_leaf_node(uc);//产生该字符的一个新的叶节点。
            ++(*pSF)[uc]->count;//如果uc不是一个新的字符,则当前字符出现的频数累加1
            ++total_count;//总计数值加1
        }
    
        return total_count;//返回值为总计数值
    }

    new_leaf_node()函数:

    static huffman_node*
    new_leaf_node(unsigned char symbol)/*新建一个叶节点*/
    {
        huffman_node *p = (huffman_node*)malloc(sizeof(huffman_node));
        p->isLeaf = 1;//1表示是叶节点
        p->symbol = symbol;//将新的符号的值存入symbol中
        p->count = 0;//该节点的频数为初始化0
        p->parent = 0;//该节点父节点初始化为0
        return p;
    }

    建立Huffman树并计算符号对应的Huffman码字

    1.按频率从小到大排序并建立Huffman树

    static SymbolEncoder*
    calculate_huffman_codes(SymbolFrequencies * pSF)
    {
        unsigned int i = 0;
        unsigned int n = 0;
        huffman_node *m1 = NULL, *m2 = NULL;
        SymbolEncoder *pSE = NULL;
    
    #if 0
        printf("BEFORE SORT\n");
        print_freqs(pSF);
    #endif
    
        /* 按升序对符号频率数组进行排序 */
        qsort((*pSF), MAX_SYMBOLS, sizeof((*pSF)[0]), SFComp);//数组的起始地址,数组的元素数,每个元素的大小,比较函数的指针
        //将所有的节点按照字符概率小到大排序,可使用qsort函数对节点结构体进行排序。排序的依据是SFComp,即根据每个字符发生的概率进行排序。
    #if 0   
        printf("AFTER SORT\n");
        print_freqs(pSF);
    #endif
    
        /*得到文件出现的字符种类数   */
        for(n = 0; n < MAX_SYMBOLS && (*pSF)[n]; ++n)
            ;
    
        /*
         * Construct a Huffman tree. This code is based
         * on the algorithm given in Managing Gigabytes
         * by Ian Witten et al, 2nd edition, page 34.
         * Note that this implementation uses a simple
         * count instead of probability.
         构建霍夫曼树
         */
        for(i = 0; i < n - 1; ++i)
        {
            /* 将m1和m2设置为最小概率的两个子集。 */
                m1 = (*pSF)[0];
            m2 = (*pSF)[1];
    
            /* 将m1和m2替换为一个集合{m1,m2},其概率是m1和m2之和的概率。*/
    
            //合并m1、m2为非叶节点,count为二者count之和  
            //并将该非叶节点的左右孩子设为m1、m2  
            //将左右孩子的父节点指向该非叶节点  
            //将(*pSF)[0]指向该非叶节点
            (*pSF)[0] = m1->parent = m2->parent =
                new_nonleaf_node(m1->count + m2->count, m1, m2);//
            (*pSF)[1] = NULL;//1节点置空    
            /* 由于最小的两个频率数,进行了合并,频率大小发生改变,所以重新排序 */
            qsort((*pSF), n, sizeof((*pSF)[0]), SFComp);
        }
    
        /* Build the SymbolEncoder array from the tree. */
        pSE = (SymbolEncoder*)malloc(sizeof(SymbolEncoder));
        //定义一个指针数组,数组中每个元素是指向码节点的指针
        memset(pSE, 0, sizeof(SymbolEncoder));
        build_symbol_encoder((*pSF)[0], pSE);
        return pSE;
    }

    qsort函数是编译器函数库自带的快速排序函数。函数的四个变量分别是数组的起始地址,数组的元素数,每个元素的大小,比较函数的指针。在本程序中,sFcomp指向自定义的用于比较的函数sFcomp()

    static int
    SFComp(const void *p1, const void *p2)
    {
        const huffman_node *hn1 = *(const huffman_node**)p1;
        const huffman_node *hn2 = *(const huffman_node**)p2;
    
        /* 用于将所有NULL排到最后 */
        if(hn1 == NULL && hn2 == NULL)
            return 0;//若两者都为空,则返回相等
        if(hn1 == NULL)
            return 1;//若返回值为1,大于0,则hn1排到hn2后
        if(hn2 == NULL)
            return -1;若返回值为-1,小于0,则hn2排到hn1后
        /*由小到大排列*/
        if(hn1->count > hn2->count)
            return 1;
        else if(hn1->count < hn2->count)
            return -1;
    
        return 0;
    }

    这里写图片描述
    2.遍历递归Huffman树,对存在的每个字符计算码字

    /*
     * build_symbol_encoder builds a SymbolEncoder by walking
     * down to the leaves of the Huffman tree and then,
     * for each leaf, determines its code.
     */
    static void
    build_symbol_encoder(huffman_node *subtree, SymbolEncoder *pSF)
    {
        if(subtree == NULL)
            return;//判断是否是空树, 是则说明编码结束,
    
        if(subtree->isLeaf)//判断是否为树叶节点,是则产生新的码字
            (*pSF)[subtree->symbol] = new_code(subtree);
        else
        {//
            build_symbol_encoder(subtree->zero, pSF);//遍历左子树,调用build_symbol_encoder函数自身
            build_symbol_encoder(subtree->one, pSF);//遍历右子数
        }
    }

    new_code从霍夫曼树叶中构建一个huffman_code

    static huffman_code*
    new_code(const huffman_node* leaf)
    {
        /* 通过走到根节点然后反转位来构建huffman代码,
        因为霍夫曼代码是通过走下树来计算的。*/
        //采用向上回溯的方法
        unsigned long numbits = 0;//表示码长,以位为单位
        unsigned char* bits = NULL;//表示指向码字的指针
        huffman_code *p;
    
        while(leaf && leaf->parent)//用来判断节点和父节点是否存在,leaf为NULL时,不进行编码;parent为NULL时,已经到达树根不在编码
        {
            huffman_node *parent = leaf->parent;
            unsigned char cur_bit = (unsigned char)(numbits % 8);//current_bit为当前在bits[]的第几位
    
            unsigned long cur_byte = numbits / 8;//current_byte
    
            /* 如果码字长度超过一个字节,那么就在分配一个字节 */
            if(cur_bit == 0)
            {
                size_t newSize = cur_byte + 1;
                bits = (char*)realloc(bits, newSize);
                /*realloc()函数先判断当前的指针是否有足够的连续空间,如果有,扩大bits指向的地址,并且将bits返回,如果空间不够,先按照newsize指定的大小分配空间,将原有数据从头到尾拷贝到新分配的内存区域,而后释放原来bits所指内存区域(注意:原来指针是自动释放,不需要使用free),同时返回新分配的内存区域的首地址。即重新分配存储器块的地址。*/
                bits[newSize - 1] = 0; /* Initialize the new byte. */
            }
    
    //如果是左孩子,则不用改变数值,因为初始化为0。如果是右孩子,则将该位置1
            if(leaf == parent->one)
                bits[cur_byte] |= 1 << cur_bit;//将1左移至cur_bit,再将其与bits[cur_byte]进行或的操作
    
            ++numbits;//码字位数加1
            leaf = parent;//下一位的码字在当前码字的父节点一级
        }
    
        if(bits)//将现有的码字进行反转
            reverse_bits(bits, numbits);
    
        p = (huffman_code*)malloc(sizeof(huffman_code));
        p->numbits = numbits;//码长赋给节点的numbits
        p->bits = bits;//码字付给节点的bits
        return p;//返回值为码字
    }

    对码字进行倒序的函数reverse()

    static void
    reverse_bits(unsigned char* bits, unsigned long numbits)
    {
        unsigned long numbytes = numbytes_from_numbits(numbits);//将numbits除8后上取整得到numbytes
        unsigned char *tmp =
            (unsigned char*)alloca(numbytes);//alloca()是内存分配函数,在栈上申请空间,用完后马上就释放
        unsigned long curbit;
        long curbyte = 0;//记录即将要反转的二进制码所在的的数组下标
    
        memset(tmp, 0, numbytes); //将数组tmp[numbytes]所有元素置为为0
    
        for(curbit = 0; curbit < numbits; ++curbit)
        {
            unsigned int bitpos = curbit % 8;//表示curbit不是8的倍数时需要左移的位数
    
            if(curbit > 0 && curbit % 8 == 0)//curbit为8的倍数时,进入下一个字节
                ++curbyte;
    
            tmp[curbyte] |= (get_bit(bits, numbits - curbit - 1) << bitpos);
        }
    
        memcpy(bits, tmp, numbytes);//将tmp临时数组内容拷贝到bits数组中
    }
    

    get_bits函数

    //第i位在第 i/8 字节的第 i%8 位,把这一位移到字节最低位,和 0000 0001 做与,从而只留下这一位,
    static unsigned char
    get_bit(unsigned char* bits, unsigned long i)
    {
        return (bits[i / 8] >> i % 8) & 1;
    }

    3.将码表写入文件

    static int
    write_code_table(FILE* out, SymbolEncoder *se, unsigned int symbol_count)
    {
        unsigned long i, count = 0;
    
        /* 计算se中的字符种类数. */
        for(i = 0; i < MAX_SYMBOLS; ++i)
        {
            if((*se)[i])
                ++count;
        }
    
        /* Write the number of entries in network byte order. */
        i = htonl(count);    //在网络传输中,采用big-endian序,对于0x0A0B0C0D ,传输顺序就是0A 0B 0C 0D ,
        //因此big-endian作为network byte order,little-endian作为host byte order。
        //little-endian的优势在于unsigned char/short/int/long类型转换时,存储位置无需改变
        if(fwrite(&i, sizeof(i), 1, out) != 1)
            return 1;//将字符种类的个数写入文件
    
        /* Write the number of bytes that will be encoded. */
        symbol_count = htonl(symbol_count);
        if(fwrite(&symbol_count, sizeof(symbol_count), 1, out) != 1)
            return 1;//将字符数写入文件
    
        /* Write the entries. */
        for(i = 0; i < MAX_SYMBOLS; ++i)
        {
            huffman_code *p = (*se)[i];
            if(p)
            {
                unsigned int numbytes;
                /* 写入1字节的符号 */
                fputc((unsigned char)i, out);
                /* 写入一字节的码长 */
                fputc(p->numbits, out);
                /* 写入numbytes字节的码字*/
                numbytes = numbytes_from_numbits(p->numbits);
                if(fwrite(p->bits, 1, numbytes, out) != numbytes)
                    return 1;
            }
        }
    
        return 0;
    }

    第二次扫描文件,对文件查表进行Huffman编码

    static int
    do_file_encode(FILE* in, FILE* out, SymbolEncoder *se)
    {
        unsigned char curbyte = 0;
        unsigned char curbit = 0;
        int c;
    
        while((c = fgetc(in)) != EOF)//遍历文件的每一个字符
        {
            unsigned char uc = (unsigned char)c;
            huffman_code *code = (*se)[uc];//查表
            unsigned long i;
            /*将码字写入文件*/
            for(i = 0; i < code->numbits; ++i)
            {
                /* Add the current bit to curbyte. */
                curbyte |= get_bit(code->bits, i) << curbit;
    
                /* If this byte is filled up then write it
                 * out and reset the curbit and curbyte. */
                if(++curbit == 8)
                {
                    fputc(curbyte, out);
                    curbyte = 0;
                    curbit = 0;
                }
            }
        }

    输出统计结果

    定义用于输出统计结果的结构体

    typedef struct huffman_statistics_result
    {
        float freq[256];//用于记录每个信源符号出现的频次
        unsigned long numbits[256];
        unsigned char bits[256][100];//用来存放码字,规定每个码字的最大长度为100
    }huffman_stat;
    
    int huffST_getSymFrequencies(SymbolFrequencies *SF, huffman_stat *st,int total_count)
    {
        int i,count =0;
        for(i = 0; i < MAX_SYMBOLS; ++i)
        {   
            if((*SF)[i])
            {
                st->freq[i]=(float)(*SF)[i]->count/total_count;
                count+=(*SF)[i]->count;
            }
            else 
            {
                st->freq[i]= 0;
            }
        }
        if(count==total_count)
            return 1;
        else
            return 0;
    }
    
    int huffST_getcodeword(SymbolEncoder *se, huffman_stat *st)
    {
        unsigned long i,j;
    
        for(i = 0; i < MAX_SYMBOLS; ++i)
        {
            huffman_code *p = (*se)[i];
            if(p)
            {
                unsigned int numbytes;
                st->numbits[i] = p->numbits;
                numbytes = numbytes_from_numbits(p->numbits);
                for (j=0;j<numbytes;j++)
                    st->bits[i][j] = p->bits[j];
            }
            else
                st->numbits[i] =0;
        }
    
        return 0;
    }
    
    void output_huffman_statistics(huffman_stat *st,FILE *out_Table)
    {
        int i,j;
        unsigned char c;
        fprintf(out_Table,"symbol\t   freq\t   codelength\t   code\n");
        for(i = 0; i < MAX_SYMBOLS; ++i)
        {   
            fprintf(out_Table,"%d\t   ",i);
            fprintf(out_Table,"%f\t   ",st->freq[i]);
            fprintf(out_Table,"%d\t    ",st->numbits[i]);
            if(st->numbits[i])
            {
                for(j = 0; j < st->numbits[i]; ++j)
                {
                    c =get_bit(st->bits[i], j);
                    fprintf(out_Table,"%d",c);
                }
            }
            fprintf(out_Table,"\n");
        }
    }

    实验结果分析

    实验结果

    文件类型平均码长信源熵原文件大小(kb)压缩后文件大小(kb)压缩比
    doc2.7433222.5687534226102.6
    jpg7.9972637.977105663213721371
    avi7.9854017.977105663313631321.0012
    excel7.3207457.28229740487811.07
    pdf7.939537.9179153562072061
    mp48.007.91791535612134121351
    rar8.000047.99874227913225132260.9999
    mpg7.8173517.791074385398439831
    ppt7.9478277.934968073501449831.0062

    各样本文件的概率分布图

    文件类型概率分布图
    doc这里写图片描述
    jpg这里写图片描述
    avi这里写图片描述
    excel这里写图片描述
    pdf这里写图片描述
    mp4这里写图片描述
    rar这里写图片描述
    mpg这里写图片描述
    ppt这里写图片描述

    实验结果分析

    由各个文件类型经压缩编码后的平均码长和信源熵可以看出,各文件类型的平均码长和信源熵大小基本相同,平均码长无限逼近信源熵,可以验证无失真编码的平均码长界限定理。
    由编码效率可以看出,doc文件、excel文件、ppt文件和avi文件的编码效率较高,通过文件概率分布图可以看出,由于霍夫曼编码是可变长编码,因此当各个信源符号概率分布差异较大,且概率较大的信源符号个数很少时,霍夫曼编码的压缩效果最好。

    存在的疑问

    为什么码长为8,但编出的码字并不是8位的?
    这里写图片描述

    展开全文
  • tensorflow实现编码

    千次阅读 2017-03-08 22:11:48
    tensorflow实现编码

    简介

    • 自编码器是利用神经网络提取出图像中的高阶特征,同时可以利用高阶特征重构自己
    • 如果向原图中添加噪声,则可以通过高阶特征的提取,对原始图像进行去噪
    • tensorflow实战第四章内容

    代码

    import numpy as np
    import sklearn.preprocessing as prep
    import tensorflow as tf
    from tensorflow.examples.tutorials.mnist import input_data
    
    def xavier_init( fan_in, fan_out, constant = 1 ):
        low  = -constant * np.sqrt( 6.0 / ( fan_in + fan_out ) )
        high =  constant * np.sqrt( 6.0 / ( fan_in + fan_out ) )
        return tf.random_uniform((fan_in, fan_out), minval=low, maxval=high, dtype=tf.float32 )
    
    class AdditiveGaussianNoiseAutoencoder(object):
        def __init__(self, n_input, n_hidden, transfer_function=tf.nn.softplus, optimizer = tf.train.AdamOptimizer(), scale=0.1 ):
            self.n_input = n_input
            self.n_hidden = n_hidden
            self.transfer = transfer_function
            self.scale = tf.placeholder( tf.float32 )
            self.training_scale = scale
            network_weights = self._initialize_weights()
            self.weights = network_weights
    
            self.x = tf.placeholder( tf.float32, [None, self.n_input] )
            self.hidden = self.transfer( tf.add( tf.matmul(self.x + scale * tf.random_normal(( n_input, ) ), self.weights['w1'] ), self.weights['b1'] ))
            self.reconstruction = tf.add( tf.matmul( self.hidden, self.weights['w2'] ), self.weights['b2'] )
            self.cost = 0.5 * tf.reduce_sum( tf.pow( tf.subtract( self.reconstruction, self.x ), 2 ) )
            self.optimizer = optimizer.minimize( self.cost )
            init = tf.global_variables_initializer()
            self.sess = tf.Session()
            self.sess.run( init )
            print "begin to run session..."
        def _initialize_weights(self):
            all_weights = dict()
            all_weights['w1'] = tf.Variable( xavier_init( self.n_input, self.n_hidden ) )
            all_weights['b1'] = tf.Variable( tf.zeros( [self.n_hidden], dtype = tf.float32 ) )
            all_weights['w2'] = tf.Variable( tf.zeros([self.n_hidden, self.n_input], dtype = tf.float32) )
            all_weights['b2'] = tf.Variable( tf.zeros( [self.n_input], dtype = tf.float32 ) )
            return all_weights
    
        def partial_fit(self, X):
            cost, opt = self.sess.run( (self.cost, self.optimizer), 
                                    feed_dict = { self.x : X, self.scale : self.training_scale } )
            return cost
    
        def calc_total_cost( self, X ):
            return self.sess.run( self.cost, feed_dict = { self.x : X, self.scale : self.training_scale } )
    
        def transform( self, X ):
            return self.sess.run( self.hidden, feed_dict = { self.x : X, self.scale : self.training_scale } )
    
        def generate( self, hidden = None ):
            if hidden == None:
                hidden = np.random.normal( size = self.weights['b1'] )
            return self.sess.run( self.reconstruction, feed_dict = { self.hidden : hidden } )
    
        def reconstruction( self, X ):
            return self.sess.run( self.reconstruction, feed_dict = { self.x : X, self.scale : self.training_scale } )
    
        def getWeights( self ):
            return self.sess.run( self.weights['w1'] )
    
        def getBiases( self ):
            return self.sess.run( self.weights['b1'] )
    
    
    mnist = input_data.read_data_sets( '../MNIST_data', one_hot = True )
    
    def standard_scale( X_train, X_test ):
        preprocessor = prep.StandardScaler().fit( X_train )
        X_train = preprocessor.transform( X_train )
        X_test  = preprocessor.transform( X_test )
        return X_train, X_test
    
    def get_random_block_from_data( data, batch_size ):
        start_index = np.random.randint( 0, len(data) - batch_size )
        return data[ start_index : (start_index+batch_size)  ]
    
    X_train, X_test  =standard_scale( mnist.train.images, mnist.test.images )
    
    n_samples = int( mnist.train.num_examples )
    training_epochs = 20
    batch_size = 128
    display_step = 1
    
    autoencoder = AdditiveGaussianNoiseAutoencoder( n_input = 784,
                                                                                        n_hidden = 200, 
                                                                                        transfer_function = tf.nn.softplus,
                                                                                        optimizer = tf.train.AdamOptimizer( learning_rate = 0.0001 ),
                                                                                        scale = 0.01 )
    
    for epoch in range( training_epochs ):
        avg_cost = 0
        total_batch = int( n_samples / batch_size )
        for i in range( total_batch ):
            batch_xs = get_random_block_from_data( X_train, batch_size )
    
            cost = autoencoder.partial_fit( batch_xs )
            avg_cost = cost / n_samples * batch_size
    
        if epoch % display_step == 0:
            print( "epoch : %04d, cost = %.9f" % ( epoch+1, avg_cost ) )
    
    print( "Total cost : ",  str( autoencoder.calc_total_cost(X_test) 
    

    说明

    • 文件中mnist初始化时需要设置数据集的位置
    • 隐藏层的节点数越大,训练后得到的误差越小,200个节点时,测试误差为60万左右,400个节点时,测试误差为20万左右
    • 自己又加了一个隐藏层,但是效果好像不明显,随着训练次数的变化,训练误差呈现出发散的状态
    展开全文
  • 牛人写的关于RS纠错编码原理及其实现方法,编解码说明非常详细,包括流程及完整可运行的matlab程序!
  • 【Matlab编程】哈夫曼编码的Matlab实现

    万次阅读 多人点赞 2015-05-04 11:31:45
    在前年暑假的时候,用C实现了哈夫曼编译码的功能,见文章《哈夫曼树及编译码》。不过在通信仿真中,经常要...下面直接给出具体的Matlab实现的哈夫曼编码函数,由于程序中注释还算比较详细,在此就不予与说明: functio
  • 哈夫曼编码原理以及实现

    万次阅读 2016-11-26 15:32:11
    哈夫曼编码原理以及实现
  • 三个信源的自适应算术编码,c++编写,内附算法说明
  • 算术编码、译码以及matlab实现

    千次阅读 2019-10-24 20:09:01
    算术编码是一种采用的编码,我们用matlab语言来实现算术码的编码、译码...编码的语言描述,我们这里就不具体说明了,在百度百科等一系列文章中都可以找到,这里我们用matlab来实现这一过程: M=2;%二元数据 p=[0....
  • 前一段时间有一个课程,需要自己实现两种无算编码方式,并比较其效率,这确实是难倒我了,在网上找了几个但是实在不看不懂别人的程序,只能硬着头皮自己写,大概的效果还好吧,需要的人可以借鉴一下 完整的代码和...
  • Tensorflow实现稀疏自动编码(SAE)

    千次阅读 2016-12-04 11:59:12
    1.概述人在获取图像时,并不是像计算机逐个像素去读,一般是扫一眼物体,大致能得到需要的信息,如形状,颜色,特征。怎么让机器也有这项能力呢,稀疏编码来了。...上图就是稀疏编码的一半流程,清晰的说明
  • C语言实现Base64编码/解码

    万次阅读 多人点赞 2017-12-18 19:10:36
    Bse64是一种以64个可打印字符对二进制数据进行编码编码算法。base64在对数据进行编码时以三个8位字符型数据为一组,取这三个字符型数据的ASCII码,然后以6位为一组组成4个新的数据,这4个新的数据有6位,所以它的...
  • C#实现Base64编码与解码

    千次阅读 2018-07-31 11:40:39
    一、编码规则 Base64编码的思想是是采用64个基本的ASCII码字符对数据进行重新编码。它将需要编码的数据拆分成字节数组。以3个字节为一组。按顺序排列24 位数据,再把这24位数据分成4
  • Huffman编码与解码_C语言实现

    万次阅读 多人点赞 2017-04-16 10:22:22
    哈夫曼编码(Huffman Coding),是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种。Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异...本次实验用C语言实现了Huffman编码器、Huffman解码器。
  • 说明数据的冗余度在哪里。 3、手动编码也可以。最好编程实现压缩。 二、文字转国标码原理 (1)汉字机内码、区位码、国标码简介 汉字的机内码是汉字在计算机汉字系统内部的表示方法,是计算机汉字系统的基础代码...
  • 霍夫曼编码原理以及代码实现

    千次阅读 2019-05-10 09:05:03
    霍夫曼编码压缩能够实现对于自然语言文件空间大幅压缩。对于普通的文本文件字符,简单起见,如果字符为ASCII,则文本中的每个字符使用7bit来表示,如果文本中有大量的重复相同序列,使用ASCII编码来保存存储会造成...
  • 数据结构(15)--哈夫曼树以及哈夫曼编码实现

    万次阅读 多人点赞 2016-03-01 17:28:40
    代码实现 4.1哈夫曼树定义 哈夫曼树的存储结构:采用静态三叉链表 #include #include #include #define N 4//带权值的叶子节点数或者是需要编码的字符数 #define M 2*N-1//n个叶子节点构造的哈夫曼树有2n-1个结点 #...
  • 详细使用及代码说明请参照我的blog http://www.cnblogs.com/geeking/
  • Base64编码的C语言实现

    千次阅读 2016-10-23 21:29:31
    Bse64是一种以64个可打印字符对二进制数据进行编码编码算法。base64在对数据进行编码时以三个8位字符型数据为一组,取这三个字符型数据的ASCII码,然后以6位为一组组成4个新的数据,这4个新的数据有6位,所以它的...
  • 开源Faac实现PCM编码AAC

    千次阅读 多人点赞 2016-10-27 17:34:16
    目的:Faac实现PCM编码AAC环境:系统:Windows 环境:VS2015 64bit步骤:1. 下载及编译Faac1. 从官网(http://www.audiocoding.com/downloads.html)下载Faac最新版本。 2. 解压zip文件以后直接进入文件夹libfaac,在...
  • Base64编码的vbs实现

    千次阅读 2015-07-05 21:49:45
    继续vbs的学习,顺便学习...使用说明:把下面的另存为.vbs文件,然后直接拖带编码的文件到这个vbs(可以包括不可见字符)或者运行后输入待编码的数据即可。(注意:待编码文件请另存为utf-8,如下图:) Set arg
  • c++编写的简单LZ78编码程序,内附步骤说明
  • LZW编码的学习与实现

    万次阅读 多人点赞 2015-10-20 20:21:03
    看了一天,感觉终于搞明白了一点(代码终于写对了),编码过程大四的时候学过一点点,按部就班的按照步骤来做就行了,解码过程貌似课堂上老师没讲,自己看wiki上的讲解和example搞懂了。 LZW全称Lempel–Ziv–Welch...
  • 用LZW压缩算法实现编码与解码

    热门讨论 2009-12-30 17:42:50
    压缩文件有两个源码文件LZWCode.cpp和LZWDecode.cpp可以实现LZW的编码与解码,并有简要的使用说明文档。
  • 算法练习七--哈夫曼编码C++实现

    万次阅读 多人点赞 2016-03-18 20:11:07
    算法练习七–哈夫曼编码C++实现 好就没写博客了,今天在九度上遇到了个哈夫曼编码的oj题目,实现了下,发现自己大一时视之如恶魔的哈夫曼树的构造如今也能轻易实现了,哇哈哈,特此记一笔 一、哈夫曼树介绍在...
  •  利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。构造哈夫曼树时,首先将由n个字 符形成的n个叶子结点存放到数组HuffNode的前n个分量中,然后根据哈夫曼方法的基本思想,不断将...
  • sklearn实现one-hot编码处理符号型数据

    千次阅读 2018-07-25 20:30:38
    目录 1、data.csv数据 2.使用one-hot编码进行转化 1、data.csv数据 2.使用one-hot编码进行转化 ...from sklearn.feature_extraction import DictVectorizer ...函数说明:将符号特征转换为one-hot向...
  • Spring 编码过滤 -- 解析Filter实现原理

    千次阅读 2016-06-23 21:34:55
    Spring中的字符集过滤器可以很方便的为我们解决项目中出现的中文乱码问题,而且使用方法也很简单,只需要在web.xml文件中配置一下该过滤器,设置两个重要的参数(encoding和...但是本文的重点在于Filter的实现原始。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 509,568
精华内容 203,827
关键字:

编码实现如何说明