LZ77压缩算法实验报告

合集下载

lz77压缩算法java 语言实现

lz77压缩算法java 语言实现

一、介绍LZ77压缩算法是一种常用的无损数据压缩算法,由Abraham Lempel和Jacob Ziv在1977年提出。

该算法通过利用历史数据的重复性,将重复的数据替换为指向历史数据的指针,从而实现对数据的压缩。

在本文中,我们将介绍如何使用Java语言实现LZ77压缩算法,以及对其性能进行分析。

二、实现原理1. 窗口和缓冲区在LZ77压缩算法中,窗口和缓冲区是两个重要的概念。

窗口是一个固定大小的滑动窗口,用于存储历史数据。

缓冲区则是用于存储待压缩的数据。

2. 搜索和编码LZ77算法通过在窗口中搜索与缓冲区匹配的子串,并将匹配的子串用指向窗口中相应位置的指针来表示。

还需要编码匹配长度和偏移量,以实现对数据的压缩。

三、Java语言实现1. 数据结构在Java语言中,我们可以使用字符串来表示待压缩的数据。

我们需要定义一个数据结构来表示LZ77算法中的窗口和缓冲区。

在本文中,我们使用一个双向队列来表示窗口,使用一个字符数组来表示缓冲区。

2. 搜索和匹配在Java语言中,我们可以使用字符串的相关方法来实现在窗口中搜索和匹配子串的功能。

一旦找到匹配的子串,我们就可以得到匹配的长度和偏移量。

3. 编码和解码LZ77算法中的编码过程涉及到将匹配的长度和偏移量转化为指针的形式,并将其与匹配的字符一起输出。

在Java语言中,我们可以利用字符串的拼接和格式化方法来实现编码的过程。

而在解码过程中,我们需要根据指针的形式来还原出原始数据。

四、性能分析1. 时间复杂度在实现LZ77压缩算法时,搜索和匹配是算法的核心步骤。

在Java语言中,字符串的相关操作通常具有较高的时间复杂度。

在实际应用中,我们需要对算法进行优化,以提高搜索和匹配的效率。

2. 空间复杂度在Java语言中,字符串的存储通常占用较多的内存空间。

在LZ77压缩算法中,窗口和缓冲区的存储也会占用一定的内存空间。

在实际应用中,我们需要考虑如何有效地利用内存空间。

LZ77压缩算法详解

LZ77压缩算法详解

gzip 、zlib以及图形格式png,使用的压缩算法都是deflate算法。

从gzip的源码中,我们了解到了defalte 算法的原理和实现。

我阅读的gzip版本为 gzip-1.2.4。

下面我们将要对deflate算法做一个分析和说明。

首先简单介绍一下基本原理,然后详细的介绍实现。

1 gzip 所使用压缩算法的基本原理gzip 对于要压缩的文件,首先使用LZ77算法的一个变种进行压缩,对得到的结果再使用Huffman编码的方法(实际上gzip根据情况,选择使用静态Huffman编码或者动态Huffman编码,详细内容在实现中说明)进行压缩。

所以明白了LZ77算法和Huffman编码的压缩原理,也就明白了gzip的压缩原理。

我们来对LZ77算法和Huffman编码做一个简单介绍。

1.1 LZ77算法简介这一算法是由Jacob Ziv 和 Abraham Lempel 于 1977 年提出,所以命名为 LZ77。

1.1.1 LZ77算法的压缩原理如果文件中有两块内容相同的话,那么只要知道前一块的位置和大小,我们就可以确定后一块的内容。

所以我们可以用(两者之间的距离,相同内容的长度)这样一对信息,来替换后一块内容。

由于(两者之间的距离,相同内容的长度)这一对信息的大小,小于被替换内容的大小,所以文件得到了压缩。

下面我们来举一个例子。

有一个文件的内容如下 其中有些部分的内容,前面已经出现过了,下面用()括起来的部分就是相同的部分。

(http://jiurl.)nease(.net)我们使用 (两者之间的距离,相同内容的长度) 这样一对信息,来替换后一块内容。

(22,13)nease(23,4)(22,13)中,22为相同内容块与当前位置之间的距离,13为相同内容的长度。

(23,4)中,23为相同内容块与当前位置之间的距离,4为相同内容的长度。

由于(两者之间的距离,相同内容的长度)这一对信息的大小,小于被替换内容的大小,所以文件得到了压缩。

lz77编码例题详解(一)

lz77编码例题详解(一)

lz77编码例题详解(一)LZ77编码例题详细解释LZ77编码是一种无损数据压缩算法,它可以通过利用数据中的重复部分来减小数据的大小。

下面是一个对LZ77编码的例题进行详细解释。

1. LZ77编码原理LZ77编码的原理是利用前缀编码和后缀编码来表示数据中的重复部分。

具体步骤如下:1.遍历待压缩的数据,从左到右逐个字符进行处理。

2.如果当前字符在之前的字符中没有出现过,则将该字符直接输出。

3.如果当前字符在之前的字符中出现过,则向前查找最长的匹配字符串。

4.将匹配字符串的起始位置和长度编码为前缀编码。

5.将匹配字符串的后一个字符输出。

2. 例题分析下面我们通过一个例题来演示LZ77编码的过程。

待压缩的数据:abcabcabc首先,我们处理第一个字符a。

由于是第一个字符,没有前面的字符,所以直接输出:a。

2.2 第二个字符接下来,我们处理第二个字符b。

由于之前的字符中没有出现过b,所以直接输出:b。

2.3 第三个字符然后,我们处理第三个字符c。

由于之前的字符中没有出现过c,所以直接输出:c。

2.4 第四个字符接下来,我们处理第四个字符a。

此时,我们可以向前查找,发现之前的字符中出现了a,而且前面的字符aba可以与当前的字符a构成重复。

所以我们可以用前缀编码来表示这个匹配。

•匹配字符串的起始位置:向前查找的位置是第一个a,距离当前位置为3。

•匹配字符串的长度:匹配到的字符串长度为1。

所以我们可以用(3, 1)来表示这个匹配,然后输出匹配后的字符a,整体编码为:(3, 1)a。

继续处理第五个字符b。

由于之前的字符中没有出现过b,所以直接输出:b。

2.6 第六个字符然后,我们处理第六个字符c。

由于之前的字符中没有出现过c,所以直接输出:c。

2.7 第七个字符接下来,我们处理第七个字符a。

此时,我们可以向前查找,发现之前的字符中出现了a,而且前面的字符bca可以与当前的字符a构成重复。

所以我们可以用前缀编码来表示这个匹配。

数据压缩实验报告(3篇)

数据压缩实验报告(3篇)

第1篇一、实验目的1. 了解数据压缩的基本原理和方法。

2. 掌握常用数据压缩算法的应用。

3. 分析不同数据压缩算法的性能和适用场景。

二、实验环境1. 操作系统:Windows 102. 编程语言:Python3. 数据压缩工具:Huffman编码、LZ77、LZ78、RLE、JPEG、PNG三、实验内容1. Huffman编码2. LZ77编码3. LZ78编码4. RLE编码5. 图像压缩:JPEG、PNG四、实验步骤1. Huffman编码(1)设计Huffman编码树,计算每个字符的频率。

(2)根据频率构建Huffman编码树,为每个字符分配编码。

(3)将原始数据按照Huffman编码进行编码,得到压缩数据。

(4)解压缩:根据编码表还原原始数据。

2. LZ77编码(1)设计LZ77编码算法,查找匹配的字符串。

(2)将原始数据按照LZ77编码进行编码,得到压缩数据。

(3)解压缩:根据编码表还原原始数据。

3. LZ78编码(1)设计LZ78编码算法,查找匹配的字符串。

(2)将原始数据按照LZ78编码进行编码,得到压缩数据。

(3)解压缩:根据编码表还原原始数据。

4. RLE编码(1)设计RLE编码算法,统计连续字符的个数。

(2)将原始数据按照RLE编码进行编码,得到压缩数据。

(3)解压缩:根据编码表还原原始数据。

5. 图像压缩:JPEG、PNG(1)使用JPEG和PNG工具对图像进行压缩。

(2)比较压缩前后图像的质量和大小。

五、实验结果与分析1. Huffman编码(1)压缩前后数据大小:原始数据大小为100KB,压缩后大小为25KB。

(2)压缩效率:压缩比约为4:1。

2. LZ77编码(1)压缩前后数据大小:原始数据大小为100KB,压缩后大小为35KB。

(2)压缩效率:压缩比约为3:1。

3. LZ78编码(1)压缩前后数据大小:原始数据大小为100KB,压缩后大小为30KB。

(2)压缩效率:压缩比约为3.3:1。

LZ77 压缩算法实验报告 一

LZ77 压缩算法实验报告 一

LZ77 压缩算法实验报告一、实验内容:使用 C++编程实现 LZ77 压缩算法的实现。

二、实验目的:用 LZ77 实现文件的压缩。

三、实验环境: 1、软件环境:Visual C++ 6.02、编程语言:C++四、实验原理: LZ77 算法在某种意义上又可以称为“滑动窗口压缩”,这是由于该算法将一个虚拟的,可以跟随压缩进程滑动的窗口作为术语字典,要压缩的字符串如果在该窗口中出现,则输出其出现位置和长度。

使用固定大小窗口进行术语匹配,而不是在所有已经编码的信息中匹配,是因为匹配算法的时间消耗往往很多,必须限制字典的大小才能保证算法的效率;随着压缩的进程滑动字典窗口,使其中总包含最近编码过的信息,是因为对大多数信息而言,要编码的字符串往往在最近的上下文中更容易找到匹配串。

五、 LZ77 算法的基本流程:1、从当前压缩位置开始,考察未编码的数据,并试图在滑动窗口中找出最长的匹配字符串,如果找到,则进行步骤2,否则进行步骤 3。

2、输出三元符号组 ( off, len, c )。

其中 off 为窗口中匹配字符串相对窗口边界的偏移,len 为可匹配的长度,c 为下一个字符。

然后将窗口向后滑动 len + 1 个字符,继续步骤 1。

3、输出三元符号组 ( 0, 0, c )。

其中 c 为下一个字符。

然后将窗口向后滑动 len + 1 个字符,继续步骤 1。

代码如下:#include<windows.h>#include<stdio.h>#include<memory.h>#include"lz77.h"//////////////////////////////////////////////////////////////////// out file format:// 0;flag2;buffer;0;flag2;buffer;...flag1;flag2;bufferlast// flag1 - 2 bytes, source buffer block length// if block size is 65536, be zero// flag2 - 2 bytes, compressed buffer length// if can not compress, be same with flag1//////////////////////////////////////////////////////////////////void main(int argc, char* argv[]){/*if (argc != 4){puts("Usage: ");printf(" Compress : %s c sourcefile destfile\n", argv[0]); printf(" Decompress : %s d sourcefile destfile\n", argv[0]); return;} */BYTE soubuf[65536];BYTE destbuf[65536 + 16];FILE* in;FILE* out;/* in = fopen("input.txt", "rb");if (in == NULL){puts("Can't open source file");return;}out = fopen("compress.txt", "wb");if (out == NULL){puts("Can't open dest file");fclose(in);return;}fseek(in, 0, SEEK_END);long soulen = ftell(in);fseek(in, 0, SEEK_SET);CCompressLZ77 cc;WORD flag1, flag2; */int temp;printf("compress(0) or decompress(1)?:");scanf("%d",&temp);if (temp == 0) // compress{in = fopen("input.txt", "rb");if (in == NULL){puts("Can't open source file");return;}out = fopen("compress.txt", "wb");if (out == NULL){puts("Can't open dest file");fclose(in);return;}fseek(in, 0, SEEK_END);long soulen = ftell(in);fseek(in, 0, SEEK_SET);CCompressLZ77cc;WORD flag1, flag2;int last = soulen, act;while ( last > 0 ){act = min(65536, last);fread(soubuf, act, 1, in);last -= act;if (act == 65536) // out 65536 bytesflag1 = 0;else// out last blocksflag1 = act;fwrite(&flag1, sizeof(WORD), 1, out);int destlen = press((BYTE*)soubuf, act, (BYTE*)destbuf);if (destlen == 0) // can't compress the block{flag2 = flag1;fwrite(&flag2, sizeof(WORD), 1, out);fwrite(soubuf, act, 1, out);}else{flag2 = (WORD)destlen;fwrite(&flag2, sizeof(WORD), 1, out);fwrite(destbuf, destlen, 1, out);}}}else if (temp == 1) // decompress{in = fopen("compress.txt", "rb");if (in == NULL){puts("Can't open source file");return;}out = fopen("decompress.txt", "wb");if (out == NULL){puts("Can't open dest file");fclose(in);return;}fseek(in, 0, SEEK_END);long soulen = ftell(in);fseek(in, 0, SEEK_SET);CCompressLZ77cc;WORD flag1, flag2;int last = soulen, act;while (last > 0){fread(&flag1, sizeof(WORD), 1, in);fread(&flag2, sizeof(WORD), 1, in);last -= 2 * sizeof(WORD);if (flag1 == 0)act = 65536;elseact = flag1;last-= flag2 ? (flag2) : act;if (flag2 == flag1){fread(soubuf, act, 1, in);}else{fread(destbuf, flag2, 1, in);if (!cc.Decompress((BYTE*)soubuf, act, (BYTE*)destbuf)){puts("Decompress error");fclose(in);fclose(out);return;}}fwrite((BYTE*)soubuf, act, 1, out);}}else{puts("Usage: ");printf(" Compress : %s c sourcefile destfile\n", argv[0]);printf(" Decompress : %s d sourcefile destfile\n", argv[0]);}fclose(in);fclose(out);}//////////////////////////////// LZ77.h//////////////////////////////// 使用在自己的堆中分配索引节点,不滑动窗口// 每次最多压缩65536 字节数据// 的优化版本#ifndef_WIX_LZ77_COMPRESS_HEADER_001_#define_WIX_LZ77_COMPRESS_HEADER_001_// 滑动窗口的字节大小#define_MAX_WINDOW_SIZE65536class CCompress{public:CCompress() {};virtual ~CCompress() {};public:virtual int Compress(BYTE* src, int srclen, BYTE* dest) = 0;virtual BOOL Decompress(BYTE* src, int srclen, BYTE* dest) = 0;protected:// tools/////////////////////////////////////////////////////////// CopyBitsInAByte : 在一个字节范围内复制位流// 参数含义同CopyBits 的参数// 说明:// 此函数由CopyBits 调用,不做错误检查,即// 假定要复制的位都在一个字节范围内void CopyBitsInAByte(BYTE* memDest, int nDestPos,BYTE* memSrc, int nSrcPos, int nBits);////////////////////////////////////////////////////////// CopyBits : 复制内存中的位流// memDest - 目标数据区// nDestPos - 目标数据区第一个字节中的起始位// memSrc - 源数据区// nSrcPos - 源数据区第一个字节的中起始位// nBits - 要复制的位数// 说明:// 起始位的表示约定为从字节的高位至低位(由左至右)// 依次为0,,... , 7// 要复制的两块数据区不能有重合void CopyBits(BYTE* memDest, int nDestPos,BYTE* memSrc, int nSrcPos, int nBits);//////////////////////////////////////////////////////////////// 将DWORD值从高位字节到低位字节排列void InvertDWord(DWORD* pDW);/////////////////////////////////////////////////////////////// 设置byte的第iBit位为aBit// iBit顺序为高位起从记数(左起)void SetBit(BYTE* byte, int iBit, BYTE aBit);////////////////////////////////////////////////////////////// 得到字节byte第pos位的值// pos顺序为高位起从记数(左起)BYTE GetBit(BYTE byte, int pos);////////////////////////////////////////////////////////////// 将位指针*piByte(字节偏移), *piBit(字节内位偏移)后移num位void MovePos(int* piByte, int* piBit, int num);/////////////////////////////////////////////////////////// 取log2(n)的upper_boundint UpperLog2(int n);/////////////////////////////////////////////////////////// 取log2(n)的lower_boundint LowerLog2(int n);};class CCompressLZ77 : public CCompress{public:CCompressLZ77();virtual ~CCompressLZ77();public://///////////////////////////////////////////// 压缩一段字节流// src - 源数据区// srclen - 源数据区字节长度, srclen <= 65536// dest - 压缩数据区,调用前分配srclen字节内存// 返回值> 0 压缩数据长度// 返回值= 0 数据无法压缩// 返回值< 0 压缩中异常错误int Compress(BYTE* src, int srclen, BYTE* dest);/////////////////////////////////////////////// 解压缩一段字节流// src - 接收原始数据的内存区, srclen <= 65536// srclen - 源数据区字节长度// dest - 压缩数据区// 返回值- 成功与否BOOL Decompress(BYTE* src, int srclen, BYTE* dest);protected:BYTE* pWnd;// 窗口大小最大为64k ,并且不做滑动// 每次最多只压缩64k 数据,这样可以方便从文件中间开始解压// 当前窗口的长度int nWndSize;// 对滑动窗口中每一个字节串排序// 排序是为了进行快速术语匹配// 排序的方法是用一个k大小的指针数组// 数组下标依次对应每一个字节串:(00 00) (00 01) ... (01 00) (01 01) ...// 每一个指针指向一个链表,链表中的节点为该字节串的每一个出现位置struct STIDXNODE{WORD off; // 在src中的偏移WORD off2; // 用于对应的字节串为重复字节的节点// 指从off 到off2 都对应了该字节串WORD next; // 在SortHeap中的指针};WORD SortTable[65536]; // 256 * 256 指向SortHeap中下标的指针// 因为窗口不滑动,没有删除节点的操作,所以// 节点可以在SortHeap 中连续分配struct STIDXNODE* SortHeap;int HeapPos; // 当前分配位置// 当前输出位置(字节偏移及位偏移)int CurByte, CurBit;protected:////////////////////////////////////////// 输出压缩码// code - 要输出的数// bits - 要输出的位数(对isGamma=TRUE时无效)// isGamma - 是否输出为γ编码void_OutCode(BYTE* dest, DWORD code, int bits, BOOL isGamma);///////////////////////////////////////////////////////////// 在滑动窗口中查找术语// nSeekStart - 从何处开始匹配// offset, len - 用于接收结果,表示在滑动窗口内的偏移和长度// 返回值- 是否查到长度为或以上的匹配字节串BOOL_SeekPhase(BYTE* src, int srclen, int nSeekStart, int* offset, int* len);///////////////////////////////////////////////////////////// 得到已经匹配了个字节的窗口位置offset// 共能匹配多少个字节inline int_GetSameLen(BYTE* src, int srclen, int nSeekStart, int offset);//////////////////////////////////////////// 将窗口向右滑动n个字节inline void_ScrollWindow(int n);// 向索引中添加一个字节串inline void_InsertIndexItem(int off);// 初始化索引表,释放上次压缩用的空间void_InitSortTable();};#endif// _WIX_LZW_COMPRESS_HEADER_001_ //////////////////////////////// LZ77.CPP//////////////////////////////#include<windows.h>#include<stdio.h>#include<memory.h>#include<crtdbg.h>#include"lz77.h"///////////////////////////////////////////////////////// // 取log2(n)的upper_boundint CCompress::UpperLog2(int n){int i = 0;if (n > 0){int m = 1;while(1){if (m >= n)return i;m <<= 1;i++;}}elsereturn -1;}// UpperLog2////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // 取log2(n)的lower_boundint CCompress::LowerLog2(int n){int i = 0;if (n > 0){int m = 1;while(1){if (m == n)return i;if (m > n)return i - 1;m <<= 1;i++;}}elsereturn -1;}// LowerLog2/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 将位指针*piByte(字节偏移), *piBit(字节内位偏移)后移num位void CCompress::MovePos(int* piByte, int* piBit, int num) {num += (*piBit);(*piByte) += num / 8;(*piBit) = num % 8;}// MovePos////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 得到字节byte第pos位的值// pos顺序为高位起从记数(左起)BYTE CCompress::GetBit(BYTE byte, int pos){int j = 1;j <<= 7 - pos;if (byte & j)return 1;elsereturn 0;}// GetBit//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 设置byte的第iBit位为aBit// iBit顺序为高位起从记数(左起)void CCompress::SetBit(BYTE* byte, int iBit, BYTE aBit){if (aBit)(*byte) |= (1 << (7 - iBit));else(*byte) &= ~(1 << (7 - iBit));}// SetBit////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 将DWORD值从高位字节到低位字节排列void CCompress::InvertDWord(DWORD* pDW){union UDWORD{ DWORD dw; BYTE b[4]; };UDWORD* pUDW = (UDWORD*)pDW;BYTE b;b = pUDW->b[0]; pUDW->b[0] = pUDW->b[3]; pUDW->b[3] = b;b = pUDW->b[1]; pUDW->b[1] = pUDW->b[2]; pUDW->b[2] = b; }// InvertDWord//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// CopyBits : 复制内存中的位流// memDest - 目标数据区// nDestPos - 目标数据区第一个字节中的起始位// memSrc - 源数据区// nSrcPos - 源数据区第一个字节的中起始位// nBits - 要复制的位数// 说明:// 起始位的表示约定为从字节的高位至低位(由左至右)// 依次为0,,... , 7// 要复制的两块数据区不能有重合void CCompress::CopyBits(BYTE* memDest, int nDestPos,BYTE* memSrc, int nSrcPos, int nBits){int iByteDest = 0, iBitDest;int iByteSrc = 0, iBitSrc = nSrcPos;int nBitsToFill, nBitsCanFill;while (nBits > 0){// 计算要在目标区当前字节填充的位数nBitsToFill = min(nBits, iByteDest ? 8 : 8 - nDestPos);// 目标区当前字节要填充的起始位iBitDest = iByteDest ? 0 : nDestPos;// 计算可以一次从源数据区中复制的位数nBitsCanFill = min(nBitsToFill, 8 - iBitSrc);// 字节内复制CopyBitsInAByte(memDest + iByteDest, iBitDest,memSrc + iByteSrc, iBitSrc, nBitsCanFill);// 如果还没有复制完nBitsToFill 个if (nBitsToFill > nBitsCanFill){iByteSrc++; iBitSrc = 0; iBitDest += nBitsCanFill;CopyBitsInAByte(memDest + iByteDest, iBitDest,memSrc + iByteSrc, iBitSrc,nBitsToFill - nBitsCanFill);iBitSrc += nBitsToFill - nBitsCanFill;}else{iBitSrc += nBitsCanFill;if (iBitSrc >= 8){iByteSrc++; iBitSrc = 0;}}nBits -= nBitsToFill; // 已经填充了nBitsToFill位iByteDest++;}}// CopyBits//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// CopyBitsInAByte : 在一个字节范围内复制位流// 参数含义同CopyBits 的参数// 说明:// 此函数由CopyBits 调用,不做错误检查,即// 假定要复制的位都在一个字节范围内void CCompress::CopyBitsInAByte(BYTE* memDest, int nDestPos, BYTE* memSrc, int nSrcPos, int nBits){BYTE b1, b2;b1 <<= nSrcPos; b1 >>= 8 - nBits; // 将不用复制的位清b1 <<= 8 - nBits - nDestPos; // 将源和目的字节对齐*memDest |= b1; // 复制值为的位b2 = 0xff; b2 <<= 8 - nDestPos; // 将不用复制的位置b1 |= b2;b2 = 0xff; b2 >>= nDestPos + nBits;b1 |= b2;*memDest &= b1; // 复制值为的位}// CopyBitsInAByte///////////////////////////////////////////////////////////------------------------------------------------------------------CCompressLZ77::CCompressLZ77(){SortHeap = new struct STIDXNODE[_MAX_WINDOW_SIZE]; }CCompressLZ77::~CCompressLZ77(){delete[] SortHeap;}// 初始化索引表,释放上次压缩用的空间void CCompressLZ77::_InitSortTable(){memset(SortTable, 0, sizeof(WORD) * 65536);nWndSize = 0;HeapPos = 1;}// 向索引中添加一个字节串void CCompressLZ77::_InsertIndexItem(int off){WORD q;BYTE ch1, ch2;ch1 = pWnd[off]; ch2 = pWnd[off + 1];if (ch1 != ch2){// 新建节点HeapPos++;SortHeap[q].off = off;SortHeap[q].next = SortTable[ch1 * 256 + ch2];SortTable[ch1 * 256 + ch2] = q;}else{// 对重复字节串// 因为没有虚拟偏移也没有删除操作,只要比较第一个节点// 是否和off 相连接即可q = SortTable[ch1 * 256 + ch2];if (q != 0 && off == SortHeap[q].off2 + 1){// 节点合并SortHeap[q].off2 = off;}else{// 新建节点q = HeapPos;HeapPos++;SortHeap[q].off = off;SortHeap[q].off2 = off;SortHeap[q].next = SortTable[ch1 * 256 + ch2];SortTable[ch1 * 256 + ch2] = q;}}}//////////////////////////////////////////// 将窗口向右滑动n个字节void CCompressLZ77::_ScrollWindow(int n){for (int i = 0; i < n; i++){nWndSize++;if (nWndSize > 1)_InsertIndexItem(nWndSize - 2);}}///////////////////////////////////////////////////////////// 得到已经匹配了个字节的窗口位置offset// 共能匹配多少个字节int CCompressLZ77::_GetSameLen(BYTE* src, int srclen, int nSeekStart, int offset) {int i = 2; // 已经匹配了个字节int maxsame = min(srclen - nSeekStart, nWndSize - offset);while (i < maxsame&& src[nSeekStart + i] == pWnd[offset + i])i++;_ASSERT(nSeekStart + i <= srclen && offset + i <= nWndSize);return i;}///////////////////////////////////////////////////////////// 在滑动窗口中查找术语// nSeekStart - 从何处开始匹配// offset, len - 用于接收结果,表示在滑动窗口内的偏移和长度// 返回值- 是否查到长度为或以上的匹配字节串BOOL CCompressLZ77::_SeekPhase(BYTE* src, int srclen, int nSeekStart, int* offset, int* len){int j, m, n;if (nSeekStart < srclen - 1){BYTE ch1, ch2;ch1 = src[nSeekStart]; ch2 = src[nSeekStart + 1];WORD p;p = SortTable[ch1 * 256 + ch2];if (p != 0){m = 2; n = SortHeap[p].off;while (p != 0){j = _GetSameLen(src, srclen,nSeekStart, SortHeap[p].off);if ( j > m ){m = j;n = SortHeap[p].off;}p = SortHeap[p].next;}(*offset) = n;(*len) = m;return TRUE;}}return FALSE;}////////////////////////////////////////// 输出压缩码// code - 要输出的数// bits - 要输出的位数(对isGamma=TRUE时无效)// isGamma - 是否输出为γ编码void CCompressLZ77::_OutCode(BYTE* dest, DWORD code, int bits, BOOL isGamma){if ( isGamma ){BYTE* pb;DWORD out;// 计算输出位数int GammaCode = (int)code - 1;int q = LowerLog2(GammaCode);if (q > 0){out = 0xffff;pb = (BYTE*)&out;// 输出q个CopyBits(dest + CurByte, CurBit,pb, 0, q);MovePos(&CurByte, &CurBit, q);}// 输出一个out = 0;pb = (BYTE*)&out;CopyBits(dest + CurByte, CurBit, pb + 3, 7, 1);MovePos(&CurByte, &CurBit, 1);if (q > 0){// 输出余数, q位int sh = 1;sh <<= q;out = GammaCode - sh;pb = (BYTE*)&out;InvertDWord(&out);CopyBits(dest + CurByte, CurBit,pb + (32 - q) / 8, (32 - q) % 8, q);MovePos(&CurByte, &CurBit, q);}}else{DWORD dw = (DWORD)code;BYTE* pb = (BYTE*)&dw;InvertDWord(&dw);CopyBits(dest + CurByte, CurBit,pb + (32 - bits) / 8, (32 - bits) % 8, bits);MovePos(&CurByte, &CurBit, bits);}}/////////////////////////////////////////////// 压缩一段字节流// src - 源数据区// srclen - 源数据区字节长度// dest - 压缩数据区,调用前分配srclen+5字节内存// 返回值> 0 压缩数据长度// 返回值= 0 数据无法压缩// 返回值< 0 压缩中异常错误int CCompressLZ77::Compress(BYTE* src, int srclen, BYTE* dest) {int i;CurByte = 0; CurBit = 0;int off, len;if (srclen > 65536)return -1;pWnd = src;_InitSortTable();for (i = 0; i < srclen; i++){if (CurByte >= srclen)return 0;if (_SeekPhase(src, srclen, i, &off, &len)){// 输出匹配术语flag(1bit) + len(γ编码) + offset(最大bit)_OutCode(dest, 1, 1, FALSE);_OutCode(dest, len, 0, TRUE);// 在窗口不满k大小时,不需要位存储偏移_OutCode(dest, off, UpperLog2(nWndSize), FALSE);_ScrollWindow(len);i += len - 1;}else{// 输出单个非匹配字符0(1bit) + char(8bit)_OutCode(dest, 0, 1, FALSE);_OutCode(dest, (DWORD)(src[i]), 8, FALSE);_ScrollWindow(1);}}int destlen = CurByte + ((CurBit) ? 1 : 0);if (destlen >= srclen)return 0;return destlen;}/////////////////////////////////////////////// 解压缩一段字节流// src - 接收原始数据的内存区// srclen - 源数据区字节长度// dest - 压缩数据区// 返回值- 成功与否BOOL CCompressLZ77::Decompress(BYTE* src, int srclen, BYTE* dest) {int i;CurByte = 0; CurBit = 0;pWnd = src; // 初始化窗口nWndSize = 0;if (srclen > 65536)return FALSE;for (i = 0; i < srclen; i++){BYTE b = GetBit(dest[CurByte], CurBit);MovePos(&CurByte, &CurBit, 1);if (b == 0) // 单个字符{CopyBits(src + i, 0, dest + CurByte, CurBit, 8);MovePos(&CurByte, &CurBit, 8);nWndSize++;}else// 窗口内的术语{int q = -1;while (b != 0){q++;b = GetBit(dest[CurByte], CurBit);MovePos(&CurByte, &CurBit, 1);}int len, off;DWORD dw = 0;BYTE* pb;if (q > 0){pb = (BYTE*)&dw;CopyBits(pb + (32 - q) / 8, (32 - q) % 8, dest + CurByte, CurBit, q);MovePos(&CurByte, &CurBit, q);InvertDWord(&dw);len = 1;len <<= q;len += dw;len += 1;}elselen = 2;// 在窗口不满k大小时,不需要位存储偏移dw = 0;pb = (BYTE*)&dw;int bits = UpperLog2(nWndSize);CopyBits(pb + (32 - bits) / 8, (32 - bits) % 8, dest + CurByte, CurBit, bits);MovePos(&CurByte, &CurBit, bits);InvertDWord(&dw);off = (int)dw;// 输出术语for (int j = 0; j < len; j++){_ASSERT(i + j < srclen);_ASSERT(off + j < _MAX_WINDOW_SIZE);src[i + j] = pWnd[off + j];}nWndSize += len;i += len - 1;}// 滑动窗口if (nWndSize > _MAX_WINDOW_SIZE){pWnd += nWndSize - _MAX_WINDOW_SIZE;nWndSize = _MAX_WINDOW_SIZE;}}return TRUE;}。

LZ77算法在文本压缩中的应用

LZ77算法在文本压缩中的应用

LZ77算法在文本压缩中的应用LZ77(Lempel-Ziv 77)算法是一种经典的文本压缩算法,于1977年由Jacob Ziv和Abraham Lempel提出。

LZ77算法基于一种称为“滑动窗口”的模式匹配思想。

它通过在滑动窗口内查找重复的字串,并使用指针(offset)和长度(length)来表示这些重复的字串。

使用这些指针和长度信息,可以将原始文本用更短的编码来表示,从而达到压缩数据大小的目的。

在阶段,LZ77算法从输入文本的开头开始,逐个字符进行。

它通过维护一个滑动窗口来最长的匹配字串。

滑动窗口首先是一个固定大小的缓冲区,起始位置为输入文本的开头,滑动窗口的大小可以根据具体的实现进行调整。

然后,LZ77算法逐个字符将输入文本推进滑动窗口,并在滑动窗口内与当前字符相匹配的最长字串。

这一过程可以使用各种字符串匹配算法来实现,常见的有暴力和Knuth-Morris-Pratt算法等。

一旦找到匹配的字串,LZ77算法记录指针和长度信息,并将其添加到输出流中。

指针(offset)表示匹配字串在滑动窗口中的位置,长度(length)表示匹配字串的长度。

然后,LZ77算法将滑动窗口推进到匹配字串的末尾,并继续进行。

如果没有找到匹配的字串,LZ77算法将当前字符作为一个独立的字节(literal)添加到输出流中,并将滑动窗口推进一个字符。

在编码阶段,LZ77算法将阶段产生的指针、长度和字节组合成一个编码对(<offset,length>, byte)的形式,并将其输出。

输出的编码对可以按照具体的格式进行存储,常见的有二进制格式和可打印的ASCII文本格式。

对于非压缩的字节,LZ77算法将其作为literal直接添加到输出流中。

最终,LZ77算法输出的数据流就是压缩后的文本。

LZ77算法的应用非常广泛,特别是在网络传输和存储领域。

由于网络带宽和存储容量的限制,需要对数据进行压缩以减少传输和存储成本。

lz77编码例题详解

lz77编码例题详解

lz77编码例题详解LZ77编码是一种无损数据压缩算法,它通过利用重复出现的数据来减少存储空间。

这种编码算法广泛应用于网络传输、数据存储和多媒体压缩等领域。

本文将详细解释LZ77编码的原理,并通过一个具体的例题加以说明。

LZ77编码的原理很简单。

算法从输入串的开头开始,依次扫描每个字符,并通过一个滑动窗口来进行匹配。

滑动窗口是一个固定大小的缓冲区,用于存储已经遍历过的字符。

当匹配到重复的字符时,算法将记录下重复字符之前的距离和重复字符个数,以此作为压缩数据的表示。

这样,在压缩数据中,只需要保存重复字符之前的距离和重复字符的个数,而不需要重复存储相同的字符。

假设输入序列为:ABABABA,滑动窗口大小为4。

算法的工作流程如下:1. 初始化滑动窗口和输出缓冲区。

初始状态下,滑动窗口为空,而输出缓冲区为一个空串。

2. 从输入串的开头开始扫描。

在此例中,我们首先扫描到字符"A"。

因为滑动窗口为空,所以直接将字符"A"添加到滑动窗口,并将其输出到缓冲区,即输出"A"。

3. 继续扫描下一个字符"B"。

此时滑动窗口为"A",并且滑动窗口中的字符与下一个字符"B"不匹配。

因此,将字符"B"添加到滑动窗口,并将其输出到缓冲区,即输出"B"。

4. 继续扫描下一个字符"A"。

此时滑动窗口为"AB",并且滑动窗口中的字符与下一个字符"A"匹配。

算法会记录下重复字符"A"之前的距离和重复字符的个数。

在这个例子中,距离为1,重复字符个数为1。

因此,将输出"<1,1>",表示重复字符之前的距离为1,重复字符个数为1。

5. 继续扫描下一个字符"B"。

压缩率高的压缩算法

压缩率高的压缩算法

压缩率高的压缩算法随着信息技术的不断发展,数据的存储和传输需求也越来越大。

为了更高效地利用存储空间和提高网络传输速度,压缩算法应运而生。

压缩算法是通过对数据进行编码和解码,以减少数据的存储空间和传输带宽的占用。

在众多压缩算法中,有一些算法以其高压缩率而著名。

一、LZ77压缩算法LZ77是一种基于字典的压缩算法,它通过利用重复出现的字符串来减少数据的存储空间。

该算法在编码过程中,将字符串分成固定大小的窗口,并在窗口内查找匹配的字符串。

编码时,将匹配的字符串用指针指向之前出现的位置,并记录匹配字符串之后的字符。

解码时,根据指针和记录的字符,可以还原出原始字符串。

LZ77算法在文本和图像等数据中具有较好的压缩效果,能够显著减少存储空间的占用。

二、哈夫曼编码哈夫曼编码是一种变长编码算法,它通过对频率较高的字符使用较短的编码,对频率较低的字符使用较长的编码,从而达到高压缩率的效果。

该算法首先统计字符出现的频率,然后根据频率构建哈夫曼树。

树的叶子节点表示字符,路径上的编码表示字符的编码。

编码时,将字符替换为对应的编码,解码时,根据编码树还原原始字符。

哈夫曼编码在文本和图像等数据中具有较高的压缩率,能够有效减少存储空间的占用。

三、算术编码算术编码是一种连续编码算法,它通过对数据中的每个符号进行编码,从而实现高压缩率的效果。

该算法将数据的范围映射到一个连续的区间,编码时,根据符号在区间中的位置来确定编码。

解码时,根据编码和区间映射关系还原原始数据。

算术编码在文本和图像等数据中具有较高的压缩率,能够极大地减少存储空间的占用。

四、LZW压缩算法LZW是一种基于字典的压缩算法,它通过建立字典来减少数据的存储空间。

该算法在编码过程中,将输入的字符串逐个字符地添加到字典中,并记录对应的编码。

当输入的字符串在字典中已经存在时,将其对应的编码输出,并将其与下一个字符组合成新的字符串添加到字典中。

解码时,根据编码和字典还原原始字符串。

LZ77压缩算法C语言实现

LZ77压缩算法C语言实现

/********************************************************************* ** Project description:* Lz77 compression/decompression algorithm.**********************************************************************/#include <windows.h>#include <conio.h>#include <stdio.h>#include <assert.h>#define OFFSET_CODING_LENGTH (10)#define MAX_WND_SIZE 1024//#define MAX_WND_SIZE (1<<OFFSET_CODING_LENGTH)#define OFFSET_MASK_CODE (MAX_WND_SIZE-1)const ULONG m=3;UCHAR __buffer1__[0x200000];UCHAR __buffer2__[0x200000];////////////////////////////////////////////////////////////////////////////////voidWrite1ToBitStream(PUCHAR pBuffer,ULONG ulBitOffset){ULONG ulByteBoundary;ULONG ulOffsetInByte;ulByteBoundary = ulBitOffset>>3 ;ulOffsetInByte = ulBitOffset&7;*(pBuffer+ulByteBoundary) |= (1<<ulOffsetInByte);}voidWrite0ToBitStream(PUCHAR pBuffer,ULONG ulBitOffset){ULONG ulByteBoundary;ULONG ulOffsetInByte;ulByteBoundary = ulBitOffset>>3 ;ulOffsetInByte = ulBitOffset&7;*(pBuffer+ulByteBoundary) &= (~(1<<ulOffsetInByte));}ULONGReadBitFromBitStream(PUCHAR pBuffer,ULONG ulBitOffset){ULONG ulByteBoundary;ULONG ulOffsetInByte;ulByteBoundary = ulBitOffset>>3 ;ulOffsetInByte = ulBitOffset&7;return ((*(PULONG)(pBuffer+ulByteBoundary))>>ulOffsetInByte)&1 ; }ULONG WINAPIWriteGolombCode(ULONG x,PUCHAR pBuffer,ULONG ulBitOffset){ULONG q, r;int i;q = (x-1)>>m;r = x-(q<<m)-1;for(i=0; (ULONG)i<q; i++, ulBitOffset++){Write1ToBitStream(pBuffer, ulBitOffset);}Write0ToBitStream(pBuffer, ulBitOffset);ulBitOffset++;for(i=0; i<m; i++, ulBitOffset++){if( (r>>i)&1 ){Write1ToBitStream(pBuffer, ulBitOffset);}else{Write0ToBitStream(pBuffer, ulBitOffset);}}return m+q+1;}ULONGReadGolombCode(PULONG pulCodingLength,PUCHAR pBuffer,ULONG ulBitOffset){ULONG q, r;ULONG bit;int i;for(q=0; ;q++){bit = (ULONG)ReadBitFromBitStream(pBuffer, ulBitOffset);ulBitOffset++;if( !bit ){break;}}for(i=0, r=0; (ULONG)i<m; i++, ulBitOffset++){bit = (ULONG)ReadBitFromBitStream(pBuffer, ulBitOffset);bit <<= i;r |= bit;}*pulCodingLength = m + q + 1;return r+(q<<m)+1;}ULONGCompareStrings(PUCHAR string1,PUCHAR string2,ULONG length){ULONG i;PUCHAR p1, p2;p1 = string1;p2 = string2;for(i=0; i<length; i++){if( *p1==*p2 ){p1++;p2++;}else{break;}}return p1-string1;}void WINAPIFindLongestSubstring(PUCHAR pSourceString,PUCHAR pString,ULONG ulSourceStringLength,PULONG pulSubstringOffset,PULONG pulSubstringLength){PUCHAR pSrc;ULONG offset, length;ULONG ulMaxLength;*pulSubstringOffset = offset = 0;*pulSubstringLength = 0;if( NULL==pSourceString || NULL==pString ){return;}ulMaxLength = ulSourceStringLength;pSrc = pSourceString;while( ulMaxLength>0 ){length = CompareStrings(pSrc, pString, ulMaxLength);if( length>*pulSubstringLength ){*pulSubstringLength = length;*pulSubstringOffset = offset;}pSrc++;offset++;ulMaxLength--;}}/*voidFindLongestSubstring(PUCHAR pSourceString,PUCHAR pString,ULONG ulSourceStringLength,PULONG pulSubstringOffset,PULONG pulSubstringLength){PUCHAR pCurrentOffset;PUCHAR p1, p2;ULONG offset, length;pCurrentOffset = pSourceString;*pulSubstringOffset = offset = 0;*pulSubstringLength = length = 0;while( pCurrentOffset<pSourceString+ulSourceStringLength ){p1 = pCurrentOffset;p2 = pString;if( *p1==*p2 ){while( p1<pSourceString+ulSourceStringLength && *p1==*p2 ){p1++;p2++;}length = p1 - pCurrentOffset;}else{length = 0;}if( length>*pulSubstringLength ){*pulSubstringLength = length;*pulSubstringOffset = (ULONG)pCurrentOffset - (ULONG)pSourceString;}pCurrentOffset++;}}*/voidWriteBits(PUCHAR pDataBuffer,ULONG ulOffsetToWrite,ULONG ulBits,ULONG ulBitLength){ULONG ulDwordsOffset;ULONG ulBitsOffset, ulBitsRemained;ulDwordsOffset = ulOffsetToWrite>>5;ulBitsOffset = ulOffsetToWrite&31;ulBitsRemained = 32 - ulBitsOffset;if( 0==ulBitsOffset ){*((PULONG)pDataBuffer+ulDwordsOffset) = ulBits;}else if( ulBitsRemained>=ulBitLength ){*((PULONG)pDataBuffer+ulDwordsOffset) |= (ulBits<<ulBitsOffset); }else{*((PULONG)pDataBuffer+ulDwordsOffset) |= (ulBits<<ulBitsOffset);*((PULONG)pDataBuffer+ulDwordsOffset+1) = ulBits>>ulBitsRemained; }}voidReadBits(PUCHAR pDataBuffer,ULONG ulOffsetToRead,PULONG pulBits){ULONG ulDwordsOffset;ULONG ulBitsOffset, ulBitsLength;ulDwordsOffset = ulOffsetToRead>>5;ulBitsOffset = ulOffsetToRead&31;ulBitsLength = 32 - ulBitsOffset;*pulBits = *((PULONG)pDataBuffer+ulDwordsOffset);if( 0!=ulBitsOffset ){(*pulBits) >>= ulBitsOffset;(*pulBits) |= (*((PULONG)pDataBuffer+ulDwordsOffset+1))<<ulBitsLength; }}voidlz77compress(PUCHAR pDataBuffer,ULONG ulDataLength,PUCHAR pOutputBuffer,PULONG pulNumberOfBits){LONG iSlideWindowPtr;ULONG ulBytesCoded;ULONG ulMaxlength;PUCHAR pSlideWindowPtr;PUCHAR pUnprocessedDataPtr;ULONG offset;ULONG length;ULONG ulCodingLength;ULONG ulBitOffset;UCHAR cc;int i;iSlideWindowPtr = -MAX_WND_SIZE;pSlideWindowPtr = NULL;ulBitOffset = 0;ulBytesCoded = 0;while( ulBytesCoded<ulDataLength ){if( iSlideWindowPtr>=0 ){pSlideWindowPtr = pDataBuffer+iSlideWindowPtr;ulMaxlength = MAX_WND_SIZE;}else if( iSlideWindowPtr>=-MAX_WND_SIZE ){pSlideWindowPtr = pDataBuffer;ulMaxlength = MAX_WND_SIZE + iSlideWindowPtr;}else{pSlideWindowPtr = NULL;ulMaxlength = 0;}pUnprocessedDataPtr = pDataBuffer + ulBytesCoded;if( ulMaxlength>ulDataLength-ulBytesCoded ){ulMaxlength = ulDataLength-ulBytesCoded;}FindLongestSubstring(pSlideWindowPtr,pUnprocessedDataPtr,ulMaxlength,&offset,&length);assert( length<=MAX_WND_SIZE );assert( offset<MAX_WND_SIZE );if(length>1){Write1ToBitStream(pOutputBuffer, ulBitOffset);ulBitOffset++;for(i=0; i<OFFSET_CODING_LENGTH; i++, ulBitOffset++){if( (offset>>i)&1 ){Write1ToBitStream(pOutputBuffer, ulBitOffset);}else{Write0ToBitStream(pOutputBuffer, ulBitOffset);}}ulCodingLength = WriteGolombCode(length, pOutputBuffer, ulBitOffset);ulBitOffset += ulCodingLength;iSlideWindowPtr += length;ulBytesCoded += length;}else{Write0ToBitStream(pOutputBuffer, ulBitOffset);ulBitOffset++;cc = (*pUnprocessedDataPtr);for(i=0; i<8; i++, ulBitOffset++){if( (cc>>i)&1 ){Write1ToBitStream(pOutputBuffer, ulBitOffset);}else{Write0ToBitStream(pOutputBuffer, ulBitOffset);}}iSlideWindowPtr++;ulBytesCoded++;}}if( ulBytesCoded!=ulDataLength ){assert(ulBytesCoded==ulDataLength);}*pulNumberOfBits = ulBitOffset;}void lz77decompress(PUCHAR pDataBuffer,ULONG ulNumberOfBits,PUCHAR pOutputBuffer,PULONG pulNumberOfBytes){LONG iSlideWindowPtr;PUCHAR pSlideWindowPtr;ULONG length, offset;ULONG bit;UCHAR cc;int i;ULONG ulBytesDecoded;ULONG ulBitOffset;ULONG ulCodingLength;PUCHAR pWrite;iSlideWindowPtr = -MAX_WND_SIZE;pWrite = (PUCHAR)pOutputBuffer;ulBitOffset = 0;ulBytesDecoded = 0;while( ulBitOffset<ulNumberOfBits ){bit = ReadBitFromBitStream(pDataBuffer, ulBitOffset);ulBitOffset++;if( bit ){if( iSlideWindowPtr>=0 ){pSlideWindowPtr = pOutputBuffer + iSlideWindowPtr;}else if( iSlideWindowPtr>=-MAX_WND_SIZE ){pSlideWindowPtr = pOutputBuffer;}else{pSlideWindowPtr = NULL;}for(i=0, offset=0; i<OFFSET_CODING_LENGTH; i++, ulBitOffset++) {bit = ReadBitFromBitStream(pDataBuffer, ulBitOffset);offset |= (bit<<i);}length= ReadGolombCode(&ulCodingLength, pDataBuffer, ulBitOffset);assert(offset<MAX_WND_SIZE);if( length>MAX_WND_SIZE ){assert(length<=MAX_WND_SIZE);}ulBitOffset += ulCodingLength;RtlMoveMemory(pWrite, pSlideWindowPtr+offset, length);pWrite+=length;iSlideWindowPtr+=length;ulBytesDecoded+=length;}else{for(i=0, cc=0; i<8 ; i++, ulBitOffset++){bit = ReadBitFromBitStream(pDataBuffer, ulBitOffset);cc |= ((UCHAR)bit<<i);}*pWrite++ = cc;iSlideWindowPtr++;ulBytesDecoded++;}}*pulNumberOfBytes = ulBytesDecoded;}extern "C"void WINAPILZ77Compress(PUCHAR __pDataBuffer,ULONG __ulDataLength,PUCHAR __pOutputBuffer,PULONG __pulNumberOfBits);extern "C"void WINAPILZ77Decompress(PUCHAR __pDataBuffer,ULONG __ulNumberOfBits,PUCHAR __pOutputBuffer,PULONG __pulNumberOfBytes);intmain(int argc,char *argv[]){FILE *fp=NULL;FILE *fp1;ULONG fsize;ULONG ulNumberOfBits;ULONG ulFileCompressedSize;ULONG ulFileDecompressedSize;SYSTEMTIME t1, t2;if( 3!=argc ){printf("Usage: lz77 [/c | /d] filename\n");return -1;}// char s1[]="abcdabcdefgabcdefaffasda";// ULONG a, b;// FindLongestSubstring((PUCHAR)s1, (PUCHAR)s1+11, 11,&a, &b );// return 0;fp = fopen(argv[2], "rb");if( !fp ){return -1;}fseek(fp, 0, SEEK_END);fsize = ftell(fp);fseek(fp, 0, SEEK_SET);fread(__buffer1__, 1, fsize, fp);GetSystemTime(&t1);lz77compress(__buffer1__, fsize, __buffer2__, &ulNumberOfBits);//LZ77Compress(__buffer1__, fsize, __buffer2__, &ulNumberOfBits);GetSystemTime(&t2);ulFileCompressedSize = ((ulNumberOfBits+7)>>3);fp1=fopen("peinfo.c_", "wb+");if( !fp1 ){goto l1;}fwrite(__buffer2__, 1, ulFileCompressedSize, fp1);fclose(fp1);RtlZeroMemory(__buffer1__, sizeof(__buffer1__));lz77decompress(__buffer2__, ulNumberOfBits, __buffer1__, &ulFileDecompressedSize);//LZ77Decompress(__buffer2__, ulNumberOfBits, __buffer1__, &ulFileDecompressedSize); fp1=fopen("peinfo.d_", "wb+");if( !fp1 ){goto l1;}fwrite(__buffer1__, 1, ulFileDecompressedSize, fp1);fclose(fp1);l1:if( fp ){fclose(fp);}ULONG milliS;milliS = ((t2.wHour - t1.wHour)*3600 + (t2.wMinute-t1.wMinute)*60 + (t2.wSecond-t1.wSecond)) * 1000 + (t2.wMilliseconds-t1.wMilliseconds);printf("Totally %ld milliseconds elapsed!\n\n", milliS);printf("Press any key to exit!\n");getch();return 0;}。

python压缩算法_Pyhton编程实践:LZ77压缩算法编码Python实现原理图解

python压缩算法_Pyhton编程实践:LZ77压缩算法编码Python实现原理图解

python压缩算法_Pyhton编程实践:LZ77压缩算法编码Python实现原理图解本篇Pyhton编程实践⽂章将为⼤家讲解Pyhton编程的知识点,看完这篇⽂章会让你对Python编程的知识点有更加清晰的理解和运⽤。

前⾔LZ77算法是⽆损压缩算法,由以⾊列⼈Abraham Lempel发表于1977年。

LZ77是典型的基于字典的压缩算法,现在很多压缩技术都是基于LZ77。

鉴于其在数据压缩领域的地位,本⽂将结合图⽚和源码详细介绍其原理。

原理介绍:⾸先介绍⼏个专业术语。

1.lookahead buffer(不知道怎么⽤中⽂表述,暂时称为待编码区):等待编码的区域2. search buffer:已经编码的区域,搜索缓冲区3.滑动窗⼝:指定⼤⼩的窗,包含“搜索缓冲区”(左) + “待编码区”(右)接下来,介绍具体的编码过程:为了编码待编码区, 编码器在滑动窗⼝的搜索缓冲区查找直到找到匹配的字符串。

匹配字符串的开始字符串与待编码缓冲区的距离称为“偏移值”,匹配字符串的长度称为“匹配长度”。

编码器在编码时,会⼀直在搜索区中搜索,直到找到最⼤匹配字符串,并输出(o, l ),其中o是偏移值, l是匹配长度。

然后窗⼝滑动l,继续开始编码。

如果没有找到匹配字符串,则输出(0, 0, c),c为待编码区下⼀个等待编码的字符,窗⼝滑动“1”。

算法实现将类似下⾯的:while( lookAheadBuffer not empty ){get a pointer (position, match) to the longest matchin the window for the lookAheadBuffer;output a (position, length, char());shift the window length+1 characters along;}主要步骤为:1.设置编码位置为输⼊流的开始2.在滑窗的待编码区查找搜索区中的最⼤匹配字符串3.如果找到字符串,输出(偏移值, 匹配长度), 窗⼝向前滑动“匹配长度”4.如果没有找到,输出(0, 0, 待编码区的第⼀个字符),窗⼝向前滑动⼀个单位5.如果待编码区不为空,回到步骤2描述实在是太复杂,还是结合实例来讲解吧实例:现在有字符串“AABCBBABC”,现在对其进⾏编码。

LZ77算法

LZ77算法

LZ77算法2011-09-07 16:39:23| 分类:图像处理| 标签:|字号大中小订阅二.LZ77算法< XMLNAMESPACE PREFIX ="O" />1977年,Jacob Ziv和Abraham Lempel描述了一种基于滑动窗口缓存的技术,该缓存用于保存最近刚刚处理的文本(J. Ziv and A. Lempel, “A Universal Algorithm for Sequential Data Compression”, IEEE Transaction on Information Theory, May 1977)。

这个算法一般称为IZ77。

LZ77和它的变体发现,在正文流中词汇和短语(GIF中的图像模式)很可能会出现重复。

当出现一个重复时,重复的序列可以用一个短的编码来代替。

压缩程序扫描这样的重复,同时生成编码来代替重复序列。

随着时间的过去,编码可以重用来捕获新的序列。

算法必须设计成解压程序能够在编码和原始数据序列推导出当前的映射。

在研究LZ77的细节之前,先看一个简单的例子(J. Weiss and D. Schremp, “Putting Data on a Diet”, IEEE Spectrum, August 1993)。

考虑这样一句话:the brown fox jumped over the brown foxy jumping frog这个短语的长度总共是53个八位组= 424 bit。

算法从左向右处理这个文本。

初始时,每个字符被映射成9 bit的编码,二进制的1跟着该字符的8 bit ASCII码。

在处理进行时,算法查找重复的序列。

当碰到一个重复时,算法继续扫描直到该重复序列终止。

换句话说,每次出现一个重复时,算法包括尽可能多的字符。

碰到的第一个这样的序列是the brown fox。

这个序列被替换成指向前一个序列的指针和序列的长度。

lz77压缩算法c语言

lz77压缩算法c语言

lz77压缩算法c语言LZ77压缩算法(C语言)引言:在信息技术高速发展的今天,数据的传输和存储变得越来越重要。

为了减小数据的体积,提高传输效率,各种压缩算法应运而生。

其中,LZ77压缩算法是一种常用的无损压缩算法,它通过利用数据的重复性来实现数据压缩。

本文将以C语言为例,介绍LZ77压缩算法的原理和实现。

一、LZ77压缩算法简介LZ77压缩算法是由Abraham Lempel和Jacob Ziv于1977年提出的一种无损压缩算法。

它的基本思想是将数据流分解为长度不等的前缀和后缀,并通过记录前缀在历史数据中的位置和后缀的长度来表示数据的重复性。

这样,在传输或存储数据时,只需要记录位置和长度信息,而不需要重复传输或存储重复的数据,从而达到压缩数据的目的。

二、LZ77压缩算法实现下面我们将用C语言实现LZ77压缩算法。

假设我们有一个输入字符串input,压缩后的输出字符串为output。

我们定义一个窗口大小window_size,表示历史数据的长度。

具体实现步骤如下:1. 初始化窗口和缓冲区- 创建一个窗口,大小为window_size,用于存储历史数据。

- 创建一个缓冲区,用于存储当前的前缀和后缀。

2. 遍历输入字符串- 初始化游标index为0,表示当前处理的位置。

- 当index小于输入字符串的长度时,执行以下步骤:- 在窗口中查找与当前前缀匹配的最长子串,记为match。

- 计算match的位置和长度,分别为offset和length。

- 如果找到了匹配的子串,将offset和length记录到缓冲区,并将index移动length个位置。

- 如果未找到匹配的子串,则将当前字符添加到缓冲区,并将index移动一个位置。

3. 输出压缩结果- 遍历缓冲区,将offset、length和字符依次输出到输出字符串output。

三、示例代码下面是使用C语言实现LZ77压缩算法的示例代码:```c#include <stdio.h>#include <string.h>#define WINDOW_SIZE 256void compressLZ77(char* input, char* output) {int index = 0;int length = strlen(input);char window[WINDOW_SIZE];char buffer[WINDOW_SIZE];memset(window, 0, sizeof(window));memset(buffer, 0, sizeof(buffer));while (index < length) {int offset = 0;int maxLength = 0;// 在窗口中查找与当前前缀匹配的最长子串for (int i = 0; i < index; i++) {int len = 0;while (input[i + len] == input[index + len] && index + len < length) {len++;}if (len > maxLength) {maxLength = len;offset = i;}}// 记录匹配的位置和长度sprintf(buffer, "%d %d %c", offset, maxLength, input[index + maxLength]);// 输出到输出字符串strcat(output, buffer);// 移动游标index += (maxLength + 1);}}int main() {char input[] = "abracadabra";char output[256] = "";compressLZ77(input, output);printf("压缩结果:%s\n", output);return 0;}```四、总结通过实现以上代码,我们成功实现了LZ77压缩算法的C语言版本。

LZ77压缩算法详解

LZ77压缩算法详解

gzip 、zlib以及图形格式png,使用的压缩算法都是deflate算法。

从gzip的源码中,我们了解到了defalte 算法的原理和实现。

我阅读的gzip版本为 gzip-1.2.4。

下面我们将要对deflate算法做一个分析和说明。

首先简单介绍一下基本原理,然后详细的介绍实现。

1 gzip 所使用压缩算法的基本原理gzip 对于要压缩的文件,首先使用LZ77算法的一个变种进行压缩,对得到的结果再使用Huffman编码的方法(实际上gzip根据情况,选择使用静态Huffman编码或者动态Huffman编码,详细内容在实现中说明)进行压缩。

所以明白了LZ77算法和Huffman编码的压缩原理,也就明白了gzip的压缩原理。

我们来对LZ77算法和Huffman编码做一个简单介绍。

1.1 LZ77算法简介这一算法是由Jacob Ziv 和 Abraham Lempel 于 1977 年提出,所以命名为 LZ77。

1.1.1 LZ77算法的压缩原理如果文件中有两块内容相同的话,那么只要知道前一块的位置和大小,我们就可以确定后一块的内容。

所以我们可以用(两者之间的距离,相同内容的长度)这样一对信息,来替换后一块内容。

由于(两者之间的距离,相同内容的长度)这一对信息的大小,小于被替换内容的大小,所以文件得到了压缩。

下面我们来举一个例子。

有一个文件的内容如下 其中有些部分的内容,前面已经出现过了,下面用()括起来的部分就是相同的部分。

(http://jiurl.)nease(.net)我们使用 (两者之间的距离,相同内容的长度) 这样一对信息,来替换后一块内容。

(22,13)nease(23,4)(22,13)中,22为相同内容块与当前位置之间的距离,13为相同内容的长度。

(23,4)中,23为相同内容块与当前位置之间的距离,4为相同内容的长度。

由于(两者之间的距离,相同内容的长度)这一对信息的大小,小于被替换内容的大小,所以文件得到了压缩。

LZ77算法范文

LZ77算法范文

LZ77算法范文LZ77算法是一种基于字典的无损数据压缩算法,用于将数据序列进行压缩和解压缩。

它是LZ系列压缩算法中的一种,也是最早的一种。

LZ77算法通过利用数据序列中重复出现的子串,将重复的子串表示为指向已经存在于字典中的相同子串的指针和一个表示剩余部分的字符。

下面将详细介绍LZ77算法的原理、步骤和应用。

LZ77算法的原理是基于一种称为“滑动窗口”的数据结构。

这个窗口包含了前面已经解压缩的数据,并在窗口的末尾维护一个字典。

算法从数据序列的开头开始扫描,并根据窗口内的字典找到最长的重复子串。

然后,算法将这个子串用一个指向字典中相同子串的指针和一个表示剩余未被编码部分的字符组成的三元组来表示。

接下来,算法移动窗口,并继续扫描剩余的数据序列,重复这个过程,直到整个数据序列被压缩。

1.初始化滑动窗口和字典。

2.从数据序列的第一个字符开始,扫描序列。

3.在窗口和字典中查找最长的重复子串。

4.如果找到重复子串,则用一个指向字典中相同子串的指针和表示剩余未被编码部分的字符构成的三元组表示子串。

5.移动窗口和字典,将已经编码的数据添加到字典中。

6.继续扫描剩余的数据序列,重复步骤3-5,直到整个数据序列被压缩。

LZ77算法的应用广泛,特别是在无损数据压缩领域。

它可以用于压缩各种类型的数据,如文本、图像、音频和视频等。

由于LZ77算法能够有效地利用重复子串,可以大幅度减小数据序列的长度,从而节省存储空间和传输带宽。

然而,LZ77算法也存在一些限制和缺点。

首先,算法需要维护一个滑动窗口和字典,这会占用一定的存储空间。

其次,由于算法只能编码重复出现的子串,对于没有重复子串的序列,无法实现较好的压缩效果。

此外,LZ77算法只适用于有序的数据序列,对于无序的数据序列,例如随机数序列,压缩效果较差。

总而言之,LZ77算法是一种经典的字典压缩算法,通过利用数据序列中的重复子串,将数据进行压缩。

尽管LZ77算法存在一些限制和缺点,但它仍然被广泛应用于各种领域,为数据存储和传输提供了有效的解决方案。

LZSS压缩算法实验报告

LZSS压缩算法实验报告

实验名称:LZSS压缩算法实验报告一、实验内容使用Visual 6..0 C++编程实现LZ77压缩算法。

二、实验目的用LZSS实现文件的压缩。

三、实验原理LZSS压缩算法是词典编码无损压缩技术的一种。

LZSS压缩算法的字典模型使用了自适应的方式,也就是说,将已经编码过的信息作为字典,四、实验环境1、软件环境:Visual C++ 6.02、编程语言:C++五、实验代码#include <stdlib.h>#include <string.h>#include <ctype.h>#include <stdio.h>/* size of ring buffer */#define N 4096/* index for root of binary search trees */#define NIL N/* upper limit for g_match_len. Changed from 18 to 16 for binarycompatability with Microsoft COMPRESS.EXE and EXPAND.EXE#define F 18 */#define F 16/* encode string into position and lengthif match_length is greater than this: */#define THRESHOLD 2/* these assume little-endian CPU like Intel x86-- need byte-swap function for big endian CPU */#define READ_LE32(X) *(uint32_t *)(X)#define WRITE_LE32(X,Y) *(uint32_t *)(X) = (Y)/* this assumes sizeof(long)==4 */typedef unsigned long uint32_t;/* text (input) size counter, code (output) size counter,and counter for reporting progress every 1K bytes */static unsigned long g_text_size, g_code_size, g_print_count;/* ring buffer of size N, with extra F-1 bytesto facilitate string comparison */static unsigned char g_ring_buffer[N + F - 1];/* position and length of longest match; set by insert_node() */static unsigned g_match_pos, g_match_len;/* left & right children & parent -- these constitute binary search tree */ static unsigned g_left_child[N + 1], g_right_child[N + 257], g_parent[N + 1]; /* input & output files */static FILE *g_infile, *g_outfile;/***************************************************************************** initialize trees*****************************************************************************/ static void init_tree(void){unsigned i;/* For i = 0 to N - 1, g_right_child[i] and g_left_child[i] will be the right and left children of node i. These nodes need not be initialized.Also, g_parent[i] is the parent of node i. These are initialized toNIL (= N), which stands for 'not used.'For i = 0 to 255, g_right_child[N + i + 1] is the root of the treefor strings that begin with character i. These are initializedto NIL. Note there are 256 trees. */for(i = N + 1; i <= N + 256; i++)g_right_child[i] = NIL;for(i = 0; i < N; i++)g_parent[i] = NIL;}/***************************************************************************** Inserts string of length F, g_ring_buffer[r..r+F-1], into one of thetrees (g_ring_buffer[r]'th tree) and returns the longest-match positionand length via the global variables g_match_pos and g_match_len.If g_match_len = F, then removes the old node in favor of the newone, because the old one will be deleted sooner.Note r plays double role, as tree node and position in buffer.*****************************************************************************/ static void insert_node(int r){unsigned char *key;unsigned i, p;int cmp;cmp = 1;key = &g_ring_buffer[r];p = N + 1 + key[0];g_right_child[r] = g_left_child[r] = NIL;g_match_len = 0;while(1){if(cmp >= 0){if(g_right_child[p] != NIL)p = g_right_child[p];else{g_right_child[p] = r;g_parent[r] = p;return;}}else{if(g_left_child[p] != NIL)p = g_left_child[p];else{g_left_child[p] = r;g_parent[r] = p;return;}}for(i = 1; i < F; i++){cmp = key[i] - g_ring_buffer[p + i];if(cmp != 0)break;}if(i > g_match_len){g_match_pos = p;g_match_len = i;if(g_match_len >= F)break;}}g_parent[r] = g_parent[p];g_left_child[r] = g_left_child[p];g_right_child[r] = g_right_child[p];g_parent[g_left_child[p]] = r;g_parent[g_right_child[p]] = r;if(g_right_child[g_parent[p]] == p)g_right_child[g_parent[p]] = r;elseg_left_child[g_parent[p]] = r;g_parent[p] = NIL; /* remove p */}/***************************************************************************** deletes node p from tree*****************************************************************************/ static void delete_node(unsigned p){unsigned q;if(g_parent[p] == NIL)return; /* not in tree */if(g_right_child[p] == NIL)q = g_left_child[p];else if(g_left_child[p] == NIL)q = g_right_child[p];else{q = g_left_child[p];if(g_right_child[q] != NIL){do q = g_right_child[q];while(g_right_child[q] != NIL);g_right_child[g_parent[q]] = g_left_child[q];g_parent[g_left_child[q]] = g_parent[q];g_left_child[q] = g_left_child[p];g_parent[g_left_child[p]] = q;}g_right_child[q] = g_right_child[p];g_parent[g_right_child[p]] = q;}g_parent[q] = g_parent[p];if(g_right_child[g_parent[p]] == p)g_right_child[g_parent[p]] = q;elseg_left_child[g_parent[p]] = q;g_parent[p] = NIL;}/***************************************************************************** *****************************************************************************/ static void compress(void){unsigned i, len, r, s, last_match_length, code_buf_ptr;unsigned char code_buf[17], mask;int c;init_tree(); /* initialize trees *//* code_buf[1..16] saves eight units of code, and code_buf[0] works aseight flags, "1" representing that the unit is an unencoded letter (1 byte), "0" a position-and-length pair (2 bytes). Thus, eight units require at most16 bytes of code. */code_buf[0] = 0;code_buf_ptr = mask = 1;s = 0;r = N - F;/* Clear the buffer with any character that will appear often. */ memset(g_ring_buffer + s, ' ', r - s);/* Read F bytes into the last F bytes of the buffer */for(len = 0; len < F; len++){c = getc(g_infile);if(c == EOF)break;g_ring_buffer[r + len] = c;}g_text_size = len;if(g_text_size == 0) /* text of size zero */return;/* Insert the F strings, each of which begins with one or more 'space' characters. Note the order in which these strings are inserted.This way, degenerate trees will be less likely to occur. */for(i = 1; i <= F; i++)insert_node(r - i);/* Finally, insert the whole string just read. The global variablesg_match_len and g_match_pos are set. */insert_node(r);do{/* g_match_len may be spuriously long near the end of text. */if(g_match_len > len)g_match_len = len;/* Not long enough match. Send one byte. */if(g_match_len <= THRESHOLD){g_match_len = 1;code_buf[0] |= mask; /* 'send one byte' flag */code_buf[code_buf_ptr] = g_ring_buffer[r]; /* Send uncoded. */code_buf_ptr++;/* Send position and length pair. Note g_match_len > THRESHOLD. */ }else{code_buf[code_buf_ptr] = (unsigned char)g_match_pos;code_buf_ptr++;code_buf[code_buf_ptr] = (unsigned char)(((g_match_pos >> 4) & 0xF0) |(g_match_len - (THRESHOLD + 1)));code_buf_ptr++;}/* Shift mask left one bit. */mask <<= 1;if(mask == 0){/* Send at most 8 units of code together */for(i = 0; i < code_buf_ptr; i++)putc(code_buf[i], g_outfile);g_code_size += code_buf_ptr;code_buf[0] = 0;code_buf_ptr = mask = 1;}last_match_length = g_match_len;for(i = 0; i < last_match_length; i++){c = getc(g_infile);break;/* Delete old strings and read new bytes */delete_node(s);g_ring_buffer[s] = c;/* If the position is near the end of buffer, extend the bufferto make string comparison easier. */if(s < F - 1)g_ring_buffer[s + N] = c;/* Since this is a ring buffer, increment the position modulo N. */s = (s + 1) & (N - 1);r = (r + 1) & (N - 1);/* Register the string in g_ring_buffer[r..r+F-1] */insert_node(r);}/* Reports progress each time the g_text_size exceeds multiples of 1024. */ g_text_size += i;if(g_text_size > g_print_count){printf("%12ld\r", g_text_size);g_print_count += 1024;}while(i++ < last_match_length)/* After the end of text, */{delete_node(s); /* no need to read, but */s = (s + 1) & (N - 1);r = (r + 1) & (N - 1);len--;if(len)insert_node(r);/* buffer may not be empty. */}} while(len > 0); /* until length of string to be processed is zero *//* Send remaining code. */if(code_buf_ptr > 1){for(i = 0; i < code_buf_ptr; i++)putc(code_buf[i], g_outfile);g_code_size += code_buf_ptr;}/* Encoding is done. */printf("In : %ld bytes\n", g_text_size);printf("Out: %ld bytes\n", g_code_size);/* xxx - floating-point math: */printf("Out/In: %.3f\n", (double)g_code_size / g_text_size);}/***************************************************************************** Just the reverse of compress()*****************************************************************************/ static void decompress(void){unsigned r, flags;int c, i, j, k;memset(g_ring_buffer, ' ', N - F);r = N - F;for(flags = 0; ; flags >>= 1){/* Get a byte. For each bit of this byte:1=copy one byte literally, from input to output0=get two more bytes describing length and position of previously-seendata, and copy that data from the ring buffer to output */if((flags & 0x100) == 0){c = getc(g_infile);if(c == EOF)break;/* uses higher byte cleverly to count eight */flags = c | 0xFF00;}/* 1=copy one byte literally, from input to output */if(flags & 1){c = getc(g_infile);if(c == EOF)break;putc(c, g_outfile);g_ring_buffer[r] = c;r = (r + 1) & (N - 1);}/* 0=get two more bytes describing length and position of previously-seen data, and copy that data from the ring buffer to output */else{i = getc(g_infile);if(i == EOF)break;j = getc(g_infile);if(j == EOF)break;i |= ((j & 0xF0) << 4);j = (j & 0x0F) + THRESHOLD;for(k = 0; k <= j; k++){c = g_ring_buffer[(i + k) & (N - 1)];putc(c, g_outfile);g_ring_buffer[r] = c;r = (r + 1) & (N - 1);}}}}/***************************************************************************** *****************************************************************************/ int main(int arg_c, char *arg_v[]){char ms_hdr[14] = "SZDD堭'3A";unsigned long size;/* check args */if(arg_c != 4)USAGE: {printf("'lzss c file1 file2' compresses file1 into file2\n""'lzss u file2 file1' uncompresses file2 into file1\n");return 1;}if(strpbrk(arg_v[1], "CcUu") == NULL)goto USAGE;/* open input file */g_infile = fopen(arg_v[2], "rb");if(g_infile == NULL){printf("Can't open input file '%s'\n", arg_v[2]);return 2;}/* get size of (uncompressed) input file */fseek(g_infile, 0, SEEK_END);size = ftell(g_infile);fseek(g_infile, 0, SEEK_SET);/* open output file */g_outfile = fopen(arg_v[3], "wb");if(g_outfile == NULL){printf("Can't open output file '%s'\n", arg_v[3]);fclose(g_infile);return 2;}/* compress or decompress */if(toupper(*arg_v[1]) == 'C'){/* write Microsoft COMPRESS/EXPAND header */WRITE_LE32(ms_hdr + 10, size);if(fwrite(ms_hdr, 1, 14, g_outfile) != 14){printf("Error writing output file '%s'\n", arg_v[3]);fclose(g_infile);fclose(g_outfile);remove(arg_v[3]);}compress();}else{/* read and validate Microsoft COMPRESS/EXPAND header */if(fread(ms_hdr, 1, 14, g_infile) != 14){printf("Error reading input file '%s'\n", arg_v[2]);fclose(g_infile);fclose(g_outfile);remove(arg_v[3]);}if(strncmp(ms_hdr, "SZDD堭'3A", 9)){printf("Input file '%s' is not COMPRESSed\n",arg_v[2]);fclose(g_infile);fclose(g_outfile);remove(arg_v[3]);}size = READ_LE32(ms_hdr + 10);decompress();}fclose(g_infile);fclose(g_outfile);return 0;}六、实验结果如果您需要使用本文档,请点击下载按钮下载!授课:XXX(注:可编辑下载,若有不当之处,请指正,谢谢!)。

lz77压缩算法c语言

lz77压缩算法c语言

lz77压缩算法c语言LZ77压缩算法是一种用于数据压缩的算法,它在计算机领域得到了广泛的应用。

本文将介绍LZ77压缩算法的原理和实现,并通过示例代码展示其在C语言中的应用。

LZ77压缩算法是由Abraham Lempel和Jacob Ziv在1977年提出的,它是一种基于字典的压缩算法。

该算法通过利用数据中的重复片段来实现数据的压缩。

具体来说,LZ77算法将数据分为两个部分:字典和未压缩数据。

字典是一个固定大小的滑动窗口,它包含了之前出现过的数据片段。

初始时,字典为空。

未压缩数据则是当前需要压缩的数据片段。

算法从未压缩数据的开头开始,依次向后扫描,寻找字典中与未压缩数据相匹配的最长前缀。

找到匹配的前缀后,算法将其表示为一个指针对(offset,length),其中offset表示匹配前缀在字典中的位置,length表示匹配的长度。

下面是LZ77压缩算法的C语言实现示例:```c#include <stdio.h>#include <stdlib.h>#include <string.h>#define WINDOW_SIZE 256#define BUFFER_SIZE 16typedef struct {int offset;int length;char next;} LZ77Pair;LZ77Pair* compress(char* input, int* size) {int inputSize = strlen(input);LZ77Pair* output = (LZ77Pair*)malloc(sizeof(LZ77Pair) * inputSize);int outputSize = 0;int windowStart = 0;int windowEnd = 0;int bufferStart = 0;int bufferEnd = BUFFER_SIZE - 1;while (bufferStart < inputSize) {int longestMatchOffset = 0;int longestMatchLength = 0;for (int i = windowStart; i < bufferStart; i++) {int j = 0;while (bufferStart + j < inputSize && input[i + j] == input[bufferStart + j]) {j++;}if (j > longestMatchLength) {longestMatchOffset = bufferStart - i;longestMatchLength = j;}}LZ77Pair pair;pair.offset = longestMatchOffset;pair.length = longestMatchLength;pair.next = input[bufferStart + longestMatchLength]; output[outputSize++] = pair;windowStart += longestMatchLength + 1;windowEnd += longestMatchLength + 1;bufferStart += longestMatchLength + 1;bufferEnd += longestMatchLength + 1;if (bufferEnd >= inputSize) {bufferEnd = inputSize - 1;}}*size = outputSize;return output;}void decompress(LZ77Pair* input, int size, char* output) {int outputSize = 0;for (int i = 0; i < size; i++) {LZ77Pair pair = input[i];for (int j = 0; j < pair.length; j++) {output[outputSize++] = output[outputSize - pair.offset - 1];}output[outputSize++] = pair.next;}output[outputSize] = '\0';}int main() {char input[] = "LZ77 is a data compression algorithm."; int inputSize = strlen(input);int compressedSize;LZ77Pair* compressed = compress(input, &compressedSize); char decompressed[inputSize + 1];decompress(compressed, compressedSize, decompressed);printf("Original: %s\n", input);printf("Compressed: ");for (int i = 0; i < compressedSize; i++) {printf("(%d,%d,%c) ", compressed[i].offset, compressed[i].length, compressed[i].next);}printf("\n");printf("Decompressed: %s\n", decompressed);free(compressed);return 0;}```上述示例中,我们首先定义了LZ77Pair结构体,用于表示压缩后的数据对。

基于LZ77算法的藏文文本压缩算法设计与实现

基于LZ77算法的藏文文本压缩算法设计与实现
用于章 节末 尾 ; 四垂符 , 于卷次 末尾 。 文书 写 习惯为 从左 到右 , 用 藏 从上 到下 , 以辅音 字母 为 主要组成 部 且 件 的特殊 拼音 文字 , 左右 拼写 、 下叠加 。藏文是 以音节 为基 本单 位 , 节拼 写 的一个 横 向单 元称 为一 个 上 音 字丁 , 每个音节 中的基本 辅音 字符 所在 的字 丁可 以是 纵 向叠加 的组合 体 , 可 以是 独 立 的辅 音字 符 , 字 也 该
第2 5卷 第 2 期
21 0 0年 1 1月
西 藏 大 学学报 ( 自然 科 学版 )
J OURN I E AL OFT B T UNI RST VE I Y
Vo -5 No2 l . 2
NO .2 O V 01
基于 L 算 法的藏文文本压 缩算 法设 计与实现 Z 7 7
边 巴旺堆 武 强 米玛加措 马元 强 桑 珠
( 西藏 大学 工 学 院 西 藏拉 萨 80 0 ) 50 0
摘要 : 随着信 息量的 不 断增加 , 用计 算机 处理 的 文本 文件 越 来越 大 , 需要 对 庞 大的 藏 文文本 进行 数 字 化 处理 , 何 节约资 源对藏 文 文本 进行 高效压 缩显得 极 为重要 。 目在 L 7 如 项 Z 7算法基 础上 结合 藏 文的特 点
通 信传输 介质 及所需 的带 宽 。
目前 , 国际 国 内对文本 压缩 的研 究 已经 取得 较 大成 果 , 出现 了基 于字典 编 码 的 L Z系列 算 法【 】 于 和基 算术 编码 等原理 的文 本压 缩算法 。 文 、 英 汉文 等文 字 的文 本压 缩技术 已经 非常 成熟 , 是藏 文文 本压缩 在 但
基金项 目: 西藏大学 国家大学 生创新性 实验计划项 目“ 基于 L 7 Z 7算法 的藏 文文本压 缩算法设计与实现” 阶段性成果 , 目 项

基于LZ77算法的图像压缩技术研究

基于LZ77算法的图像压缩技术研究

基于LZ77算法的图像压缩技术研究随着科技的进步和人们对高清图像的需求不断增长,图像压缩技术也日益成为信息领域研究的焦点之一。

而基于LZ77算法的图像压缩技术因其压缩效率高、计算复杂度低的优势逐渐受到研究者的关注,成为图像压缩技术中备受瞩目的一种。

一、LZ77算法简介LZ77算法即为“Lempel-Ziv 1977年算法”,是目前常用的无损压缩算法之一。

LZ77算法基于一种所谓的“词典编码”思想,通过构造一个固定大小的滑动窗口来实现数据压缩。

具体来说,LZ77算法通过将数据分为多个固定大小的“块”,然后在这些块之间发现重复出现的内容,并将重复内容用指向其在前面块中的“标记”来表示,从而实现数据的压缩。

在图像压缩中,LZ77算法通过识别图像中重复出现的像素块,并记录它们的位置和大小,然后将这些信息保存到压缩数据中,从而在保持图像质量的前提下实现图像的压缩。

这种方式可以使得图像的压缩比得到有效提高,同时又不会影响图像的清晰度和色彩度。

二、基于LZ77算法的图像压缩技术的优势基于LZ77算法的图像压缩技术有以下几个显著的优势:1.高效性:与其他图像压缩算法相比,基于LZ77算法的图像压缩技术能够在实现高压缩率的同时保持较快的压缩和解压速度,因此能够满足处理大量图像数据的需求。

2.适用性广:基于LZ77算法的图像压缩技术不需要考虑图像的特定颜色和分辨率等因素,因此适用性更广,能够满足不同场景下的图像处理需求。

3.可靠性高:由于基于LZ77算法的图像压缩技术采用无损压缩方式,在压缩图像时不会对图像质量造成影响,因此保证了压缩数据的可靠性。

三、基于LZ77算法的图像压缩技术的研究进展近年来,基于LZ77算法的图像压缩技术得到了广泛研究和应用。

一方面,研究者通过优化压缩算法和窗口大小,不断提高压缩率和压缩效率,例如基于LZ77算法的改进算法如LZMW、LZAS等。

另一方面,研究者结合其他算法,例如霍夫曼编码、算术编码等,不断探索基于LZ77算法的图像压缩技术的新应用,如在医学图像处理、网络传输等领域。

LZ77压缩算法详解

LZ77压缩算法详解

LZ77压缩算法详解LZ77算法基于滑动窗口的思想。

滑动窗口由一个固定大小的缓冲区和一个预定义的查找缓冲区组成。

算法通过在滑动窗口中查找已经出现过的字串,并使用查找到的字串的位置和长度来进行压缩。

LZ77算法的压缩过程如下:1.初始化滑动窗口和查找缓冲区,并将滑动窗口和查找缓冲区都设置为空。

2.从输入数据中读取一个字符,作为当前字符。

3.在滑动窗口中查找最长的已经出现过的字串,并记录字串的位置和长度。

4.将字串的位置和长度以及当前字符的编码写入输出。

5.将滑动窗口和查找缓冲区中的数据向后移动相应的位置。

6.重复步骤2-5,直到读取完全部的输入数据。

LZ77算法的解压过程如下:1.初始化滑动窗口和查找缓冲区,并将滑动窗口和查找缓冲区都设置为空。

2.从输入数据中读取一个编码,如果编码表示当前字符,则输出当前字符。

3.如果编码表示已经出现过的字串,则根据编码的位置和长度从滑动窗口中复制相应的字串,并将字串写入输出。

4.将滑动窗口和查找缓冲区中的数据向后移动相应的位置。

5.重复步骤2-4,直到读取完全部的输入数据。

LZ77压缩算法的优点是简单高效,并能有效地压缩具有重复性的数据。

但也存在一些缺点,例如算法无法处理无重复性的数据,且压缩后的数据无法进一步压缩。

因此,在实际应用中,通常会将LZ77算法与其他压缩算法结合使用,以实现更高效的压缩效果。

总的来说,LZ77压缩算法是一种经典的字典压缩算法,通过利用数据中的重复性来实现数据的压缩。

它的原理简单高效,但也存在一些限制。

在实际应用中,需要根据具体场景选择合适的压缩算法,以实现更好的压缩效果。

LZ77算法实现

LZ77算法实现

LZ77算法实现LZ77算法是一种无损压缩算法,用于将数据进行压缩,以减小存储空间或提高传输速率。

它的核心思想是利用已经出现的字符序列来代替重复出现的字符序列,从而减少需要存储或传输的数据量。

下面将详细介绍LZ77算法的实现。

缓冲区存储待压缩数据的一部分,它的大小可以根据需要进行调整。

已匹配缓冲区用于存储已找到的重复字符序列。

算法从滑动窗口的起始位置开始,逐个字符地比较缓冲区和已匹配缓冲区的内容,以找到最长的重复字符序列。

下面是LZ77算法的具体实现步骤:1.初始化滑动窗口,设置缓冲区的大小。

2.从滑动窗口的起始位置开始,逐个字符地比较缓冲区和已匹配缓冲区的内容。

3.如果在缓冲区中找到一个与已匹配缓冲区完全相同的字符序列,则将匹配长度和向前偏移量写入输出。

4.如果缓冲区中没有与已匹配缓冲区完全相同的字符序列,则将当前字符写入输出。

5.将已匹配的字符序列追加到已匹配缓冲区中,并更新滑动窗口。

6.重复步骤2-5,直到扫描完所有的字符。

7.输出压缩后的数据。

下面是一个简单的LZ77算法的实现示例:```pythonoutput = []position = 0while position < len(data):longest_match = ""match_length = 0match_position = 0for i in range(1, min(position+1, window_size+1)): substring = data[position-i:position]if substring in data[position:position+i]:match_length = imatch_position = data[position:position+i].index(substring) longest_match = substringif match_length > 0:output.append((match_length, match_position))position += match_lengthelse:output.append((0, data[position]))position += 1return outputdata = "ABABABA"window_size = 4```这个示例中的数据为"ABABABA",滑动窗口的大小为4、输出结果为[(0,'A'),(0,'B'),(0,'A'),(0,'B'),(0,'A'),(0,'B'),(0,'A')],表示每个字符都没有重复出现。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

LZ77压缩算法实验报告一、实验内容使用C++编程实现LZ77压缩算法的实现。

二、实验目的用LZ77实现文件的压缩。

三、实验环境1、软件环境:Visual C++ 6.02、编程语言:C++四、实验原理LZ77 算法在某种意义上又可以称为“滑动窗口压缩”,这是由于该算法将一个虚拟的,可以跟随压缩进程滑动的窗口作为术语字典,要压缩的字符串如果在该窗口中出现,则输出其出现位置和长度。

使用固定大小窗口进行术语匹配,而不是在所有已经编码的信息中匹配,是因为匹配算法的时间消耗往往很多,必须限制字典的大小才能保证算法的效率;随着压缩的进程滑动字典窗口,使其中总包含最近编码过的信息,是因为对大多数信息而言,要编码的字符串往往在最近的上下文中更容易找到匹配串。

五、LZ77算法的基本流程1、从当前压缩位置开始,考察未编码的数据,并试图在滑动窗口中找出最长的匹配字符串,如果找到,则进行步骤2,否则进行步骤3。

2、输出三元符号组( off, len, c )。

其中off 为窗口中匹配字符串相对窗口边界的偏移,len 为可匹配的长度,c 为下一个字符。

然后将窗口向后滑动len + 1 个字符,继续步骤1。

3、输出三元符号组( 0, 0, c )。

其中c 为下一个字符。

然后将窗口向后滑动len + 1 个字符,继续步骤1。

六、源程序/*********************************************************************** Project description:* Lz77 compression/decompression algorithm.**********************************************************************/#include <windows.h>#include <conio.h>#include <stdio.h>#include <assert.h>#define OFFSET_CODING_LENGTH (10)#define MAX_WND_SIZE 1024//#define MAX_WND_SIZE (1<<OFFSET_CODING_LENGTH)#define OFFSET_MASK_CODE (MAX_WND_SIZE-1)const ULONG m=3;UCHAR __buffer1__[0x200000];UCHAR __buffer2__[0x200000];////////////////////////////////////////////////////////////////////////////////voidWrite1ToBitStream(PUCHAR pBuffer,ULONG ulBitOffset){ULONG ulByteBoundary;ULONG ulOffsetInByte;ulByteBoundary = ulBitOffset>>3 ;ulOffsetInByte = ulBitOffset&7;*(pBuffer+ulByteBoundary) |= (1<<ulOffsetInByte);}voidWrite0ToBitStream(PUCHAR pBuffer,ULONG ulBitOffset){ULONG ulByteBoundary;ULONG ulOffsetInByte;ulByteBoundary = ulBitOffset>>3 ;ulOffsetInByte = ulBitOffset&7;*(pBuffer+ulByteBoundary) &= (~(1<<ulOffsetInByte));}ULONGReadBitFromBitStream(PUCHAR pBuffer,ULONG ulBitOffset){ULONG ulByteBoundary;ULONG ulOffsetInByte;ulByteBoundary = ulBitOffset>>3 ;ulOffsetInByte = ulBitOffset&7;return ((*(PULONG)(pBuffer+ulByteBoundary))>>ulOffsetInByte)&1 ; }ULONG WINAPIWriteGolombCode(ULONG x,PUCHAR pBuffer,ULONG ulBitOffset){ULONG q, r;int i;q = (x-1)>>m;r = x-(q<<m)-1;for(i=0; (ULONG)i<q; i++, ulBitOffset++){Write1ToBitStream(pBuffer, ulBitOffset); }Write0ToBitStream(pBuffer, ulBitOffset);ulBitOffset++;for(i=0; i<m; i++, ulBitOffset++){if( (r>>i)&1 ){Write1ToBitStream(pBuffer, ulBitOffset);}else{Write0ToBitStream(pBuffer, ulBitOffset);}}return m+q+1;}ULONGReadGolombCode(PULONG pulCodingLength,PUCHAR pBuffer,ULONG ulBitOffset){ULONG q, r;ULONG bit;int i;for(q=0; ;q++){bit = (ULONG)ReadBitFromBitStream(pBuffer, ulBitOffset);ulBitOffset++;if( !bit ){break;}}for(i=0, r=0; (ULONG)i<m; i++, ulBitOffset++){bit = (ULONG)ReadBitFromBitStream(pBuffer, ulBitOffset);bit <<= i;r |= bit;}*pulCodingLength = m + q + 1;return r+(q<<m)+1;}ULONGCompareStrings(PUCHAR string1,PUCHAR string2,ULONG length){ULONG i;PUCHAR p1, p2;p1 = string1;p2 = string2;for(i=0; i<length; i++){if( *p1==*p2 ){p1++;p2++;}else{break;}}return p1-string1;}void WINAPIFindLongestSubstring(PUCHAR pSourceString,PUCHAR pString,ULONG ulSourceStringLength,PULONG pulSubstringOffset,PULONG pulSubstringLength){PUCHAR pSrc;ULONG offset, length;ULONG ulMaxLength;*pulSubstringOffset = offset = 0;*pulSubstringLength = 0;if( NULL==pSourceString || NULL==pString ){return;}ulMaxLength = ulSourceStringLength;pSrc = pSourceString;while( ulMaxLength>0 ){length = CompareStrings(pSrc, pString, ulMaxLength);if( length>*pulSubstringLength ){*pulSubstringLength = length;*pulSubstringOffset = offset;}pSrc++;offset++;ulMaxLength--;}}/*voidFindLongestSubstring(PUCHAR pSourceString,PUCHAR pString,ULONG ulSourceStringLength,PULONG pulSubstringOffset,PULONG pulSubstringLength){PUCHAR pCurrentOffset;PUCHAR p1, p2;ULONG offset, length;pCurrentOffset = pSourceString;*pulSubstringOffset = offset = 0;*pulSubstringLength = length = 0;while( pCurrentOffset<pSourceString+ulSourceStringLength ){p1 = pCurrentOffset;p2 = pString;if( *p1==*p2 ){while( p1<pSourceString+ulSourceStringLength && *p1==*p2 ){p1++;p2++;}length = p1 - pCurrentOffset;}else{length = 0;}if( length>*pulSubstringLength ){*pulSubstringLength = length;*pulSubstringOffset = (ULONG)pCurrentOffset - (ULONG)pSourceString;}pCurrentOffset++;}}*/voidWriteBits(PUCHAR pDataBuffer,ULONG ulOffsetToWrite,ULONG ulBits,ULONG ulBitLength){ULONG ulDwordsOffset;ULONG ulBitsOffset, ulBitsRemained;ulDwordsOffset = ulOffsetToWrite>>5;ulBitsOffset = ulOffsetToWrite&31;ulBitsRemained = 32 - ulBitsOffset;if( 0==ulBitsOffset ){*((PULONG)pDataBuffer+ulDwordsOffset) = ulBits;}else if( ulBitsRemained>=ulBitLength ){*((PULONG)pDataBuffer+ulDwordsOffset) |= (ulBits<<ulBitsOffset);}else{*((PULONG)pDataBuffer+ulDwordsOffset) |= (ulBits<<ulBitsOffset);*((PULONG)pDataBuffer+ulDwordsOffset+1) = ulBits>>ulBitsRemained; }}voidReadBits(PUCHAR pDataBuffer,ULONG ulOffsetToRead,PULONG pulBits){ULONG ulDwordsOffset;ULONG ulBitsOffset, ulBitsLength;ulDwordsOffset = ulOffsetToRead>>5;ulBitsOffset = ulOffsetToRead&31;ulBitsLength = 32 - ulBitsOffset;*pulBits = *((PULONG)pDataBuffer+ulDwordsOffset);if( 0!=ulBitsOffset ){(*pulBits) >>= ulBitsOffset;(*pulBits) |= (*((PULONG)pDataBuffer+ulDwordsOffset+1))<<ulBitsLength; }}voidlz77compress(PUCHAR pDataBuffer,ULONG ulDataLength,PUCHAR pOutputBuffer,PULONG pulNumberOfBits){LONG iSlideWindowPtr;ULONG ulBytesCoded;ULONG ulMaxlength;PUCHAR pSlideWindowPtr;PUCHAR pUnprocessedDataPtr;ULONG offset;ULONG length;ULONG ulCodingLength;ULONG ulBitOffset;UCHAR cc;int i;iSlideWindowPtr = -MAX_WND_SIZE;pSlideWindowPtr = NULL;ulBitOffset = 0;ulBytesCoded = 0;while( ulBytesCoded<ulDataLength ){if( iSlideWindowPtr>=0 ){pSlideWindowPtr = pDataBuffer+iSlideWindowPtr;ulMaxlength = MAX_WND_SIZE;}else if( iSlideWindowPtr>=-MAX_WND_SIZE ){pSlideWindowPtr = pDataBuffer;ulMaxlength = MAX_WND_SIZE + iSlideWindowPtr;}else{pSlideWindowPtr = NULL;ulMaxlength = 0;}pUnprocessedDataPtr = pDataBuffer + ulBytesCoded;if( ulMaxlength>ulDataLength-ulBytesCoded ){ulMaxlength = ulDataLength-ulBytesCoded;}FindLongestSubstring(pSlideWindowPtr,pUnprocessedDataPtr,ulMaxlength,&offset,&length);assert( length<=MAX_WND_SIZE );assert( offset<MAX_WND_SIZE );if(length>1){Write1ToBitStream(pOutputBuffer, ulBitOffset);ulBitOffset++;for(i=0; i<OFFSET_CODING_LENGTH; i++, ulBitOffset++){if( (offset>>i)&1 ){Write1ToBitStream(pOutputBuffer, ulBitOffset);}else{Write0ToBitStream(pOutputBuffer, ulBitOffset);}}ulCodingLength = WriteGolombCode(length, pOutputBuffer, ulBitOffset);ulBitOffset += ulCodingLength;iSlideWindowPtr += length;ulBytesCoded += length;}else{Write0ToBitStream(pOutputBuffer, ulBitOffset);ulBitOffset++;cc = (*pUnprocessedDataPtr);for(i=0; i<8; i++, ulBitOffset++){if( (cc>>i)&1 ){Write1ToBitStream(pOutputBuffer, ulBitOffset);}else{Write0ToBitStream(pOutputBuffer, ulBitOffset);}}iSlideWindowPtr++;ulBytesCoded++;}}if( ulBytesCoded!=ulDataLength ){assert(ulBytesCoded==ulDataLength);}*pulNumberOfBits = ulBitOffset;}void lz77decompress(PUCHAR pDataBuffer,ULONG ulNumberOfBits,PUCHAR pOutputBuffer,PULONG pulNumberOfBytes){LONG iSlideWindowPtr;PUCHAR pSlideWindowPtr;ULONG length, offset;ULONG bit;UCHAR cc;int i;ULONG ulBytesDecoded;ULONG ulBitOffset;ULONG ulCodingLength;PUCHAR pWrite;iSlideWindowPtr = -MAX_WND_SIZE;pWrite = (PUCHAR)pOutputBuffer;ulBitOffset = 0;ulBytesDecoded = 0;while( ulBitOffset<ulNumberOfBits ){bit = ReadBitFromBitStream(pDataBuffer, ulBitOffset);ulBitOffset++;if( bit ){if( iSlideWindowPtr>=0 ){pSlideWindowPtr = pOutputBuffer + iSlideWindowPtr;}else if( iSlideWindowPtr>=-MAX_WND_SIZE ){pSlideWindowPtr = pOutputBuffer;}else{pSlideWindowPtr = NULL;}for(i=0, offset=0; i<OFFSET_CODING_LENGTH; i++, ulBitOffset++){bit = ReadBitFromBitStream(pDataBuffer, ulBitOffset);offset |= (bit<<i);}length= ReadGolombCode(&ulCodingLength, pDataBuffer, ulBitOffset);assert(offset<MAX_WND_SIZE);if( length>MAX_WND_SIZE ){assert(length<=MAX_WND_SIZE);}ulBitOffset += ulCodingLength;RtlMoveMemory(pWrite, pSlideWindowPtr+offset, length);pWrite+=length;iSlideWindowPtr+=length;ulBytesDecoded+=length;}else{for(i=0, cc=0; i<8 ; i++, ulBitOffset++){bit = ReadBitFromBitStream(pDataBuffer, ulBitOffset);cc |= ((UCHAR)bit<<i);}*pWrite++ = cc;iSlideWindowPtr++;ulBytesDecoded++;}}*pulNumberOfBytes = ulBytesDecoded;}extern "C"void WINAPILZ77Compress(PUCHAR __pDataBuffer,ULONG __ulDataLength,PUCHAR __pOutputBuffer,PULONG __pulNumberOfBits);extern "C"void WINAPILZ77Decompress(PUCHAR __pDataBuffer,ULONG __ulNumberOfBits,PUCHAR __pOutputBuffer,PULONG __pulNumberOfBytes);intmain(int argc,char *argv[]){FILE *fp=NULL;FILE *fp1;ULONG fsize;ULONG ulNumberOfBits;ULONG ulFileCompressedSize;ULONG ulFileDecompressedSize;SYSTEMTIME t1, t2;if( 3!=argc ){printf("Usage: lz77 [/c | /d] filename\n");return -1;}// char s1[]="abcdabcdefgabcdefaffasda";// ULONG a, b;// FindLongestSubstring((PUCHAR)s1, (PUCHAR)s1+11, 11,&a, &b ); // return 0;fp = fopen(argv[2], "rb");if( !fp ){return -1;}fseek(fp, 0, SEEK_END);fsize = ftell(fp);fseek(fp, 0, SEEK_SET);fread(__buffer1__, 1, fsize, fp);GetSystemTime(&t1);lz77compress(__buffer1__, fsize, __buffer2__, &ulNumberOfBits);//LZ77Compress(__buffer1__, fsize, __buffer2__, &ulNumberOfBits); GetSystemTime(&t2);ulFileCompressedSize = ((ulNumberOfBits+7)>>3);fp1=fopen("peinfo.c_", "wb+");if( !fp1 ){goto l1;}fwrite(__buffer2__, 1, ulFileCompressedSize, fp1);fclose(fp1);RtlZeroMemory(__buffer1__, sizeof(__buffer1__));lz77decompress(__buffer2__, ulNumberOfBits, __buffer1__, &ulFileDecompressedSize);//LZ77Decompress(__buffer2__, ulNumberOfBits, __buffer1__, &ulFileDecompressedSize); fp1=fopen("peinfo.d_", "wb+");if( !fp1 ){goto l1;}fwrite(__buffer1__, 1, ulFileDecompressedSize, fp1);fclose(fp1);l1:if( fp ){fclose(fp);}ULONG milliS;milliS = ((t2.wHour - t1.wHour)*3600 + (t2.wMinute-t1.wMinute)*60 + (t2.wSecond-t1.wSecond)) * 1000 + (t2.wMilliseconds-t1.wMilliseconds);printf("Totally %ld milliseconds elapsed!\n\n", milliS);printf("Press any key to exit!\n");getch();return 0; }七、实验结果。

相关文档
最新文档