数据压缩试验三:LZW 编码原理与C语言实现

本文详细介绍了LZW编码的基本原理,包括背景、编码思路与解码过程。通过实例展示了如何利用C语言实现LZW编码和解码,并提供了代码实现的文件结构。在编码过程中,构建词典树以实现数据压缩;解码时,通过查找词典和处理特殊情况来还原数据。
摘要由CSDN通过智能技术生成

LZW 编解码原理

背景

LZW 编码作为词典编码的一种,由 J. Ziv 和 A. Lempel 在 1978 年首次提出并由 Terry A. Welch 在 1984 年改进,最终以三人名字缩写命名。

基本原理

企图从输入的数据中创建一个“短语词典”(Dictionary Of the Phrases),这种短语可以是任意字符的组合。编码数据过程中当遇到已经在词典中出现的“短语”时,编码器就会输出这个词典中的短语的“索引号”而不是短语本身,进而达到压缩的目的。

编码

编码思路

将当前读取到的单字符记为 C(Current),将之前读取的但还未编码的字符或字符串记为 P(Previous),则编码思路可以通过以下流程图呈现
在这里插入图片描述
在最终的代码实现中,通过树的思想对词典进行构建,将每一个词条作为树中的一个节点,将每个节点(词条)定义为结构体,具有以下结构

  • 尾缀字符(suffix)
  • 母节点(parent)
  • 第一个子节点(firstChild)
  • 下一个兄弟节点(nextSibling)

此时每一个节点就可以用旧节点词条+新字符表示新的节点词条,进而简化查询步骤。

编码举例

现在以字符流“abbababac”举例,分别进行编码步骤演示与树的建立,初始化词典是用 ASCII 进行索引(a = 97,b = 98,c = 99)

步骤数 P C PC 是否在词典中 是否输出 P的索引 新增词条 说明
1 NULL a - - - 初始化词典
2 a b 是,输出97 256(ab) ab 不在词典中,扩充词典,然后 P 变为 b
3 b b 是,输出98 257(bb) bb 不在词典中,扩充词典,然后 P 变为 b
4 b a 是,输出98 258(ba) ba 不在词典中,扩充词典,然后 P 变为 a
5 a b - ab 在词典中,故不需要新建词条,P 变为 ab
6 ab a 是,输出256 259(aba) aba 不在词典中,扩充词典,然后 P 变为 a
7 a b - ab 在词典中,故不需要新建词条,P 变为 ab
8 ab a - aba 在词典中,故不需要新建词条,P 变为 aba
9 aba c 是,输出259 260(abac) abac 不在词典中,扩充词典,然后 P 变为 c
10 c NULL - 是,输出99 - 无新的字符,结束编码,输出未编码字符

相应的树为下图所示
在这里插入图片描述
以词条 “bb”为例,他的 suffix 为 b,parent 为 b,firstChild 为 NULL,nextSibling 为 ba

解码

解码思路

将当前码字记为 cW,上一个码码字记为 pW,解码思路可以通过以下框图体现
在这里插入图片描述
因为在实时编解码时,解码要比编码晚一个码字,因而存在码字词条刚被创造就被使用但在解码端还没有相应词条的情况(比如上述编码示例中的 “ababa” 字段),所以在查词典时判断若 cW 不在词典时便手动定义当前码字代表内容为“上一码字代表内容+上一码字代表内容的首字符”,以解决此类问题。

解码举例

词典在最开始已被初始化为 ASCII 码表内容,此处以“97 98 98 256 259 99”作为带解码流

步骤数 pW cW cW 是否在词典中 输出内容 新增词条 说明
1 NULL 97 a - 97 已经在词典中,因而输出 cW,新增 pW + cW 首字符
2 97 98 b ab: 256 98 已经在词典中,因而输出 cW,新增 pW + cW 首字符
3 98 98 b b b: 257 98 已经在词典中,因而输出 cW,新增 pW + cW 首字符
4 98 256 ab ba: 258 256 已经在词典中,因而输出 cW,新增 pW + cW 首字符
5 256 259 aba aba: 259 259 不在词典中,因而输出pW + pW 首字符,并将其添加到词典中
6 259 99 c abac: abac 99 已经在词典中,因而输出 cW,新增 pW + cW 首字符

代码实现

bitIO.h

#ifndef __BITIO__
#define __BITIO__

#include <stdio.h>

typedef struct
{
   
	FILE *fp;
	unsigned char mask;
	int rack;
}BITFILE;

BITFILE *OpenBitFileInput( char *filename);
BITFILE *OpenBitFileOutput( char *filename);
void CloseBitFileInput( BITFILE *bf);
void CloseBitFileOutput( BITFILE *bf);
int BitInput( BITFILE *bf);
unsigned long BitsInput( BITFILE *bf, int count);
void BitOutput( BITFILE *bf, int bit);
void BitsOutput( BITFILE *bf, unsigned long code, int count);
#endif	// __BITIO__

bitIO.c

#include <stdlib.h>
#include <stdio.h>
#include "bitio.h"
BITFILE *OpenBitFileInput( char *filename)
{
   
	BITFILE *bf;
	bf = (BITFILE *)malloc( sizeof(BITFILE));
	if( NULL == bf) return NULL;
	if( NULL == filename)	bf->fp = stdin;
	else bf->fp = fopen( filename, "rb");
	if( NULL == bf->fp) return NULL;
	bf->mask = 0x80;
	bf->rack = 0;
	return bf;
}

BITFILE *OpenBitFileOutput( char *filename)
{
   
	BITFILE *bf;
	bf = (BITFILE *)malloc( sizeof(BITFILE));
	if( NULL == bf) return NULL;
	if( NULL == filename)	bf->fp = stdout;
	else bf->fp = fopen( filename, "wb");
	if( NULL == bf->fp) return NULL;
	bf->mask = 0x80</
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值