香農編碼

信息論與編碼作業,要求用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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章