闫晨昕,江永婷,王威,王开,崔益凡—基于C语言设计的LZ78码和游程编码

何为LZ78码?

LZ78 编码是一种无损数据压缩算法,由雅各布·泽维和阿里夫·雅科文于1978年提出。它通过利用重复出现的短语来实现数据的压缩。

LZ78 编码的基本思想是构建一个字典来存储已经出现过的短语,并使用短语在字典中的索引来表示它们。编码过程中,从输入字符串的开头开始,逐个字符地读入,并检查是否已经存在于字典中的短语。如果存在,就继续读入下一个字符,然后查找新的组合是否在字典中。如果不存在,将当前短语添加到字典中,并输出它的索引以及后面的一个字符。

LZ78 编码的特点包括:

  1. 字典逐步构建:随着输入的处理,字典会逐渐增大,记录越来越多的短语。
  2. 无损压缩:LZ78 编码是一种无损数据压缩算法,可以精确还原原始数据。
  3. 字符结构化存储:短语在字典中以索引的形式存储,减少了冗余信息的存储。

虽然 LZ78 编码是一种经典的压缩算法,但它也有一些特点和限制:

  1. 空间效率:LZ78 编码使用字典来存储已出现的短语,因此需要额外的空间来存储字典。字典大小对压缩效果和解压缩负载有一定影响。
  2. 高压缩率:LZ78 编码在某些场景下可以获得很高的压缩率,特别是当输入数据中存在大量重复的短语时。
  3. 编码延迟:LZ78 编码需要依次读入字符,并进行字典的查找和更新操作,处理速度可能较慢。

LZ78码的编码算法窜写思路

总的来说,LZ78 编码是一种简单而有效的数据压缩算法,常用于无损数据压缩领域。它通过构建字典并利用短语的重复性,实现了数据的压缩和还原。

LZ78 编码的实现包括以下几个关键步骤:

  1. 定义字典:创建一个空的字典用于存储已经出现过的短语。字典可以使用数组、哈希表或其他数据结构来表示。
  2. 读取输入:从输入字符串中逐个字符读取,开始时当前短语为空。
  3. 查找字典:检查当前短语是否已经存在于字典中。如果是,则将下一个字符添加到短语中,并继续查找新的组合是否在字典中。重复这个过程,直到无法找到匹配的短语。
  4. 添加到字典:如果在字典中无法找到匹配的短语,将当前短语添加到字典中,并输出它在字典的索引值以及下一个字符。
  5. 更新当前短语:将当前短语更新为下一个字符,并返回步骤 3,继续查找和添加。
  6. 重复步骤 3 到步骤 5,直到读取完整个输入字符串。

通过这些步骤,LZ78 编码可以将输入字符串编码成一系列的 (index, character) 对。解码时,根据索引值和字符逆向构建原始字符串。

需要注意的是,字典的实现和查找过程可能会有所不同,具体取决于所选择的数据结构。此外,LZ78 编码还需要设计合适的数据表示形式和编码/解码算法,以实现压缩和还原的功能。

总的来说,LZ78 编码通过字典的创建、查找和更新来实现对输入数据的压缩,利用短语的重复性来减少冗余信息。它是一种相对简单但有效的无损数据压缩算法。

C语言设计源码

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

// 定义结构体存储编写的码表

struct 

{

char x[100];//存储第i个符号

char x1[100];//存储取出新符号与前方符号相同的符号

char now;//存储新符号

int  a;//存储前方相同符号的序号

bool b;//新符号对应的二进制码

}puttext[20];//最大长度为20

int Ki[100];//存储符号的长度

int main()

{

    char text[100];//存储接受到的码字

    int table_size=1;//码表长度

int  Sum=1;//在创建基础码表时用作计数(已经创建到了sum个字符的位置)

bool sta;//用于后方处理,找到新符号时置0,否则置1

printf("请输入所收到的码字:");

scanf("%s",text);

strncpy(puttext[0].x,text,1);//第一个符号必为新符号,将其放在码表第一位

Ki[0]=1;

for(int i=1;i<=20;i++)//i为正在建立第几个码

{

for(int j=1;j<=5;j++)//j为符号长度

{

sta=1;

strncpy(puttext[i].x,text+Sum,j);

for(int z=0;z<i;z++)

{

if(strcmp(puttext[i].x,puttext[z].x)==0)//判断是否与前方有相同符号

break;

else if(z==i-1)

{

Ki[i]=strlen(puttext[i].x);

Sum+=Ki[i];

sta=0;

table_size++;

break;

}

}

if(!sta)

break;

}

}

for(int i=0;i<table_size;i++)//设置x1的值和now的值

{

puttext[i].now=puttext[i].x[Ki[i]-1];

strncpy(puttext[i].x1,puttext[i].x,Ki[i]);

puttext[i].x1[Ki[i]-1]='\0';

if(puttext[i].x1[0]=='\0')

puttext[i].x1[0]='0';

}

for(int i=0;i<=table_size;i++)//设置ab的值

{

for(int j=0;j<=i;j++)

if(strcmp(puttext[i].x1,puttext[j].x)==0)

puttext[i].a=j+1;

if(puttext[i].now == puttext[0].x[0])

puttext[i].b = 0;

else

puttext[i].b = 1;

}

 //    输出码表

Sum=0;

for(int j=0;;j++)//查看需要多少位表示此时sum存储为多少位

{

Sum=j;

if(!(table_size>>Sum))

break;

}

    for (int i = 0;( i < table_size) && (puttext[i].x[0]!='\0'); i++)

{

printf("序号:%d    \t符号:%s    \t十进制编码:%c,%s(%d,%d)    \t二进制编码:(%d,",i+1,puttext[i].x,puttext[i].now,puttext[i].x1,puttext[i].b,puttext[i].a,puttext[i].b);

for(int j=1;Sum!=j-1;j++)//转换为二进制

{

if(1 & (puttext[i].a>>(Sum-j)))

printf("1");

else

{

printf("0");

}

}

printf(")\n");

    }

while(1);

    return 0;

}

 实验结果

何为游程编码

游程编码(Run-length Encoding,RLE)是一种简单的无损数据压缩算法,它利用连续重复出现的相同字符进行编码。它的基本思想是将连续出现的相同字符替换为字符及其出现次数的表示。

在游程编码中,重复次数称为游程(run),它是指连续出现的相同字符的数量。编码的结果是由游程长度和对应的字符构成的序列。

例如,对于字符串AAABBBCCCCD,使用游程编码后可以得到3A3B4C1D的编码结果。这个编码表示字符'A'连续出现3次,字符'B'连续出现3次,字符'C'连续出现4次,字符'D'出现1次。

游程编码适用于一些具有较高重复性的数据。当数据中存在大量连续重复的字符时,游程编码可以有效地减少数据的存储空间。然而,如果数据中没有或只有很少连续重复的字符,游程编码可能导致编码后的数据比原始数据还要长。

游程编码通常用于图像、音频和视频等领域,其中相邻像素或样本之间可能有大量连续重复的值。在这些情况下,游程编码可以显著减小数据的存储需求,从而实现数据压缩。

如何实现?

游程编码的编码过程可以概括为以下几个步骤:

  1. 初始化计数器和当前字符:将计数器count初始化为1,当前字符currentChar初始化为第一个字符。
  2. 遍历输入字符串:从第二个字符开始,依次检查每个字符。
  3. 判断字符是否与当前字符相同:
    • 如果相同,则增加计数器count的值。
    • 如果不同,则将当前字符及其计数器count的值写入编码结果中,并更新当前字符为新的字符,计数器count重置为1。
  4. 处理最后一个字符:在遍历结束后,将最后一个字符及其计数器count的值写入编码结果中。
  5. 返回编码结果:将编码结果返回作为输出。

C语言设计源码

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

// 函数声明

char *runLengthEncode(char *input);

void printEncodedResult(char *encodedResult);

int main() {

    // 输入字符串,假设字符串中只包含连续的相同字符

    char input[100];

    scanf("%s",input);

    // 游程编码

    char *encodedResult = runLengthEncode(input);

    

    // 打印编码结果

    printEncodedResult(encodedResult);

    

    // 释放内存

    free(encodedResult);

    while(1);

    return 0;

}

// 游程编码函数

char *runLengthEncode(char *input) {

    int count = 0;  // 用于计数相同字符出现的次数

    char currentChar = *input;  // 当前字符

    char *encodedResult = (char *)malloc(sizeof(char) * (2 * strlen(input) + 1));  // 存储编码结果

    char *resultPtr = encodedResult;  // 结果指针,指向当前位置

    

    while (*input != '\0') {

        if (*input == currentChar) {

            count++;

        } else {

            // 将计数和字符写入结果数组

            resultPtr += sprintf(resultPtr, "%d%c", count, currentChar);

            

            currentChar = *input;

            count = 1;

        }

        

        input++;

    }

    

    // 处理最后一个字符

    resultPtr += sprintf(resultPtr, "%d%c", count, currentChar);

    

    return encodedResult;

}

// 打印编码结果

void printEncodedResult(char *encodedResult) {

    printf("Encoded result: %s\n", encodedResult);

 实验结果

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值