LZW字典压缩算法
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define NOT_EXIST -1
//创建字典变量
typedef struct Dictionary{
char** seq; //字典字符
int* code; //字典编码
int size; //字典尺寸
int maxsize; //字典最大容量
}Dictionary;
//将字符插入字典中
//dict 字典;
//seq 字符
void insert_seq(Dictionary* dict, char* seq)
{
int i = dict->size; //字符编码
dict->seq[i] = malloc(sizeof(char) * strlen(seq) + 1); //为字典字符分配空间
dict->code[i] = i; //为字符分配编码
dict->size++; //编码+1
strcpy(dict->seq[i], seq); //将字符存入字典
}
//初始化字典
//dict 字典
//maxsize 最大容量
void init_dictionary(Dictionary* dict, int maxsize)
{
dict->maxsize = maxsize; //最大容量
dict->size = 0; //初始尺寸为0
dict->seq = malloc(sizeof(char*) * maxsize); //为字典分配空间
dict->code = malloc(sizeof(int) * maxsize); //为编码分配空间
insert_seq(dict, "#"); //将‘0’号初始化为‘#’
char seq[2] = "A"; //将'A'插入字典
for (int i = 0; i < 26; i++) //为26个字母分配编码
{
insert_seq(dict, seq); //插入字母
seq[0]++; //编码+1
}
}
//从字典获取字符编码
int get_seq_code(Dictionary* dict, char* seq)
{
for (int i = 0; i < dict->size; i++)
{
if(strcmp(dict->seq[i],seq)==0) //将给定的字符与字典比较,相等则返回编码
return dict->code[i];
}
return NOT_EXIST; //否则返回-1
}
//打印字典与编码
void print_dictionary(Dictionary* dict)
{
printf("====================\n");
printf(" Code Sequence\n");
printf("====================\n");
for (int i = 0; i < dict->size; i++)
{
printf("%5d%7c", dict->code[i], ' '); //编码
printf("%s\n", dict->seq[i]); //字符
}
printf("====================\n");
}
//对字符进行编码
void lzw_encode(char* text, Dictionary* dict)
{
char current[1000];
char next;
int code;
int i = 0;
while (i < strlen(text))
{
sprintf(current,"%c", text[i]); //将第i个字符赋值给current
next = text[i + 1]; //next为第i+1个字符
while (get_seq_code(dict, current) != NOT_EXIST) //当编码存在的时候
{
sprintf(current, "%s%c", current, next);//将current和next中的字符赋值给current
i++; //字符指针往后移
next = text[i + 1];
}
current[strlen(current) - 1] = '\0'; //当编码不存在,将current中的字符回退一个
next = text[i]; //next减去一个字符
code = get_seq_code(dict, current); //获取编码
sprintf(current, "%s%c", current, next); //将current和next中的字符赋值给current
insert_seq(dict, current); //将字符插入字典
//printf("%d %s\n", code,current); //打印编码和字符
printf("%d\n", code); //打印编码
}
}
char* get_code_seq(Dictionary* dict, int code)
{
if (code < 0 || code >= dict->size)
return NULL;
else
{
int i = code;
return dict->seq[i];
}
}
void lzw_decode(int codes[], int n, Dictionary* dict)
{
int code;
char prev[1000];
char* output;
code = codes[0];
output = get_code_seq(dict, code);
printf("%s ", output);
int i;
for (i = 1; i < n; i++)
{
strcpy(prev, output);
output = get_code_seq(dict, codes[i]);
sprintf(prev, "%s%c", prev, output[0]);
insert_seq(dict, prev);
printf("%s ", output);
}
}
int main()
{
Dictionary dict;
init_dictionary(&dict, 1000);
print_dictionary(&dict);
lzw_encode("TOBEORNOTTOBEORNOTTOBE",&dict);//编码
int arr[16] = { 20,15,2,5,15,18,14,15,20,27,29,31,33,35,28,5 };
lzw_decode(arr, 16, &dict);//解码
return 0;
}