香农编码

信息论与编码作业,要求用C语言对文本实现香农编码,要放寒假了,一并写到笔记里吧(新版编辑器居然不能对文章创建新分类了。。。。。。)
细节见注释

//我记得这段代码的注释写成于和初恋分手第二天
#include<cstdio>
#include <algorithm>
#include<iostream>
#include<cmath>
using namespace std;
struct node
{
    char a;//字符
    float b;//符号概率
    int k;//码长
    float p;//累加概率
    int n[7];//字符的最终编码
};
node *count(FILE *a,node *d)//统计文本基本信息,各个符号的符号概率
{

    char c;
    int m=0;
    c = getc(a);
    for (; c != EOF;)//统计每个字符的个数和总字符个数
    {
        d[c - 32].b++;//利用ascii码,将字符直接转换成顺序表中的位置
        c = getc(a);
        m++;
    }
    printf("包含空格在内一共%d个字符。\n", m);
    for (int i = 0; i < 95; i++)
    {
        d[i].b = d[i].b / m;//该字符的符号概率
        if (d[i].b == 0) d[i].k = 0;//符号概率为零,码长也为零
        else//求码长
        {
            //float b = 1 / d[i].b;
            //float z = log2f(b);
            float zyb = -log2f(d[i].b);
            if (zyb - (int)zyb == 0) d[i].k = zyb;
            else d[i].k = (int)(zyb + 1);
        }
    }
    /*for (int i = 0; i < 95; i++)
    {
        printf("%c=", d[i].a);
        printf("%d\n", d[i].k);
    }*/
    return d;
}
bool op(node j,node k)//按照符号概率排序
{
    return j.b > k.b;
} 
void leijia(node *j)//求累加概率
{
    for (int i = 0; i < 95; i++)
    {
        if (j[i].b == 0) break;
        if (i == 0) continue;
        j[i].p = j[i - 1].p + j[i - 1].b;//累加概率=上一个的累加概率+上一个的符号概率

    }
}
void binary(float j,int *n)//求累加概率小数部分的二进制码
{
    //int n[7] = {0};
    j = j - (int)j;
    for (int i = 0; i < 7; i++)
    {
        j = j * 2;
        n[i] = int(j);
        j = j -(float)n[i];
    }
}
void code(node *j)//最终编码,取二进制数的码长位
{

    for (int i = 0; i < 95; i++)
    {
        int m[7] = { 0 };
        binary(j[i].p, m);
        for (int s = 0; s < j[i].k; s++)
        {
            j[i].n[s] = m[s];
        }
        //memcpy(j[i].n, m, j[i].k);
    }
}
int main()
{
    node d[95];
    for (int i = 0; i < 95; i++)
    {
        d[i].a = i + 32;
        d[i].b = 0;
        d[i].k = 0;
        d[i].p = 0;
    }
    FILE *a;
    a = fopen("123.txt", "r");
    count(a, d);
    sort(d, d + 95, op);
    leijia(d);
    code(d);
    printf("字符   符号概率   累加概率   字码长度   码字 \n");
    for (int i = 0; i < 95; i++)
    {
        if (d[i].b == 0) continue;
        printf("%c      ", d[i].a);
        printf("%f   ", d[i].b);
        printf("%f      ", d[i].p);
        printf("%d        ", d[i].k);
        for (int s = 0; s < d[i].k; s++)
        {
            printf("%d", d[i].n[s]);
        }
        printf("\n");
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章