未分类

lzw编码

lzw编码也是一种压缩算法,相较于算术编码,这个的优势就是不存在稀奇古怪的精度问题,但是有一个问题就是,这个因为需要建立字典表,最终有可能造成字典表长度过长。不过这个字典表不是随着需要发送的信息一起发送的,所以最后影响的就是编码解码主机上内存占用过大。

这里有一个参考链接https://blog.csdn.net/hanzhen7541/article/details/91141112

首先,不管是编码还是解码都有一个默认的字典表,这个字典表只存最基本的字符,就比如我们这儿的字典表就只存了26个英文字母。

编码的时候我们有两个用来记录的字符串,一个叫pre,一个叫curr,开始时,pre和curr都是空串,每读入一个新的字符,令curr等于新读入的串,然后判断pre+curr是否在字典表里面,如果在的话,不输出,令pre=pre+curr,如果不在的话,此时的pre肯定在字典表里面的,然后输出此时的pre对应的编码,在字典表中添加pre+curr,然后更新pre=curr。最后新串读完后,再将此时对应的pre对应的编码添加到编码串最后。

解码的时候,我们同样设置两个记录串,一个叫pre一个叫curr。开始我们可以肯定第一个编码一定在默认字典表里面,令pre等于第一个解码出来的字符然后开始循环。循环的内容为,判断此时的编码信息是否能在字典表里面找到,若能找到的话,令curr等于该解码出来的值并直接输出为解码字符串,同时更新字典表,将pre+curr[1]添加到字典表的最后面并更新pre=curr。若不能找到的话,我们可以知道该编码值肯定由此时的pre和新加入的curr组成,而这个pre+curr肯定为下一次的pre,这样其第一个字符就是我们此时pre的第一个字符,这样我们就可以知道此时curr的值求出来就是pre+pre[0]。

下面是代码


#include <iostream>
#include <map>
#include <string>
#include <vector>

using namespace std;

int main()
{
    map<string, int> dictionary;
    map<int, string> reflect_decionary;
    string message;
    string pre = "", curr = "";
    vector<int> encoded_message;
    string tmp;
    int last = 26;

    cout << "please input your message to encode: ";
    cin >> message;

    for (int i = 0; i < 26; ++i)
    {
        tmp.push_back('a' + i);
        dictionary[tmp] = i;
        reflect_decionary[i] = tmp;
        tmp.clear();
    }

    for (int i = 0; i < message.length(); ++i)
    {
        curr = message[i];
        if (dictionary.count(pre + curr) == 0)
        {
            encoded_message.push_back(dictionary[pre]);
            dictionary[pre + curr] = last++;
            pre = curr;
        }
        else
        {
            pre = pre + curr;
        }
    }

    encoded_message.push_back(dictionary[pre]);

    pre.clear();
    curr.clear();
    message.clear();
    last = 26;

    cout << "encoded message: " << encoded_message[0] << " ";

    pre = reflect_decionary[encoded_message[0]];
    message += pre;

    for (int i = 1; i < encoded_message.size(); ++i)
    {
        cout << encoded_message[i] << " ";
        if (reflect_decionary.count(encoded_message[i]))
        {
            message += reflect_decionary[encoded_message[i]];
            curr = reflect_decionary[encoded_message[i]];
            reflect_decionary[last++] = pre + curr[0];
            pre = curr;
        }
        else
        {
            tmp = pre + pre.substr(0, 1);
            message += tmp;
            reflect_decionary[last++] = tmp;
            pre = tmp;
        }
    }
    cout << endl;

    cout << "decoded message: " << message << endl;

    return 0;
}

 

Leave a Reply

邮箱地址不会被公开。 必填项已用*标注