LZW编码与解码

C语言实现LZW编、解码

一、LZW编码介绍及原理

1、引言

LZW 是一种无损数据压缩算法,是对1978 年发表的 LZ78 的改进。LZW应用于Unix系统的标准工具、GIF图片格式以及TIFF格式等。同时LZW压缩算法对于较大规模的英文文本的压缩具有良好的效果,一般可以压缩到原来大小的一半。
LZW和哈夫曼编码一样,是无损压缩中的一种。该算法通过建立字典,实现字符重用与编码,适用于source中重复率很高的文本压缩。本文首先讲下LZW的编解码原理,然后给出LZW的实现code。

2、原理

(1)编码

LZW算法中,首先建立一个字符串表,把每一个第一次出现的字符串放入串表中,并用一个数字来表示,这个数字与此字符串在串表中的位置有关,并将这个数字存入压缩文件中,如果这个字符串再次出现时,即可用表示它的数字来代替,并将这个数字存入文件中。压缩完成后将串表丢弃。

LZW的编码原理如图所示:
在这里插入图片描述

  • 编码0-255用来存储Ascii码为[0,255]的字符,放在字典里。
  • 编码从256开始,将出现过的字符计入字典

核心思想:利用字符的可重用性,每当往结果输出一个编码,就将一个新的string存入dictionary

(2)解码

编码的逆过程,若编码是string到int的映射,我们可以将解码过程描述为int到string的映射。

  • LZW算法的解码无需在编码过程中存储字典
  • 解码初始化依旧用256个Ascii码,后面每读入一个编码(int),检查其在dictionary中的映射,并不断将新的映射加入字典

二、程序实现

1、数据结构分析

在这里插入图片描述

  • 树是动态建立的,且树中每个节点可能存在多个子节点。因此数据结构应该设计成一个节点可拥有任意个子节点,但无需为其预留空间。

  • 将树驻留在一个节点数组中,每个节点至少有两个字段:一个字符和指向母节点的指针。

  • 数据结构中没有指向子节点的指针,对沿着树从一个节点到其子节点的操作,实现方法如下:

    树用数组dict[ ]表示,数组下标用pointer表示,所以dict[pointer]表示一个节点:
    dict[pointer].suffix
    dict[pointer].parent
    dict[pointer].firstchild
    dict[pointer].nextsibling

2、c语言程序实现

(1)函数模块分析

① 初始化词典
在这里插入图片描述
② 查找字符串
在这里插入图片描述
③ 编解码功能部分(由于编码函数在实验中已给出,所以只展示解码部分)
在这里插入图片描述

(2)具体程序实现

① bitio.h

/*
 * Declaration for bitwise IO
 *
 * vim: ts=4 sw=4 cindent
 */
#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

/*
 * Definitions for bitwise IO
 *
 * vim: ts=4 sw=4 cindent
 */

#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;
	bf->rack = 0;
	return bf;
}

void CloseBitFileInput(BITFILE* bf) {
   
	fclose(bf->fp);
	free(bf);
}

void CloseBitFileOutput(BITFI
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值