C++ LZW算法

LZW算法,用于高重复率的无损文本压缩,压缩率达30%~50%,然而经过实测发现,对于普通文章文本,就算经过优化,效果也只能说很一般吧。然而这个算法的实现也让我头疼了一阵子,这种推理算法确实恶心,非常抽象,本来写完KMP之后就打算把这算法写一遍,然而为了优化,又卡住了一会,在今晚终于大功告成。


压缩部分应该很容易看明白,就是解压的时候,需要考虑如果字典里没有,则一定是连续重复的字符,就是取entry首字符不是特别容易看明白,其他看着源代码和我下面从别处找的一张图多顺着推几遍应该就能明白。若要将压缩后文本保存到文件,序列化list即可



#include<iostream>
#include<map>
#include<string>
#include<list>
#include<sstream>
#include<fstream> 
using namespace std;

void PushToResult(int count,list<string>& compressed_content,string& temp_str,map<string,int>& _map){
	char s[12];
	itoa(count,s,10);//comput now index will occupy how much space
	if(strlen(temp_str.c_str())<strlen(s)){//if compress occupy more space,choose original elem to save
		compressed_content.push_back(temp_str);
	}
	else{
		char s[12];
		itoa(_map[temp_str],s,10);
		compressed_content.push_back(s);
	}
}

void Compress(string source,list<string>& compressed_content){
	map<string,int> _map;
	int count=0;
	for(;count<256;count++){
		_map[string(1,count)]=count;
	}

	string temp_str="";
	temp_str+=source[0];//put first into temp_str
	
	char temp_char;
	for(int i=1;i<source.length();i++){
		temp_char=source[i];//temp_char start from second char
		string entry=temp_str+temp_char;
		if(_map.count(entry)){//look up wheather it is in _map
			temp_str+=temp_char;//if it is in _map,add next into temp_str
		}
		else{
			PushToResult(count,compressed_content,temp_str,_map);//push result except temp_char
			_map[entry]=count++;//push temp_str+temp_char into _map
			temp_str=temp_char;
		}
	}
	
	PushToResult(count,compressed_content,temp_str,_map);
}

string Decompress(list<string>& compressed_content){
	map<int,string> _map;
	int count=0;
	for(;count<256;count++){
		_map[count]=string(1,count);
	}
	stringstream ss;
	string temp_str="";
	string temp_entry="";
	//the same as compress to make _map,put first into temp_str
	int temp=atoi((compressed_content.front()).c_str());
	if(temp<256){
		ss<<compressed_content.front();
		temp_str+=compressed_content.front();
	}
	else{
		if(_map.count(temp)){
			ss<<_map[temp];
			temp_str+=_map[temp];
		}
	}
	
	compressed_content.pop_front();
	
	for(list<string>::iterator iter=compressed_content.begin();iter!=compressed_content.end();++iter){
		int temp=atoi((*iter).c_str());
		if(temp<256){//if not compressed
			ss<<*iter;
			temp_entry=(*iter);
		}
		else{
			if(_map.count(temp)){//if it is in _map
				ss<<_map[temp];
				temp_entry=_map[temp];
			}
			else{//it must be same char ,like aaaaa..
				temp_entry+=temp_entry[0];
				ss<<temp_entry;
			}
		}
		
		temp_str+=temp_entry[0];
		_map[count++]=temp_str;
		temp_str=temp_entry;
	}
	return ss.str();
}



int main(){
	list<string> compressed_content;
	
	ifstream in("content.txt");
	string source((istreambuf_iterator<char>(in)),istreambuf_iterator<char>());
	in.close();
	
	Compress(source,compressed_content); 
	
	string content="";
	for(list<string>::iterator iter=compressed_content.begin();iter!=compressed_content.end();++iter){
		content+=*iter;
	}
	
	cout<<"original:"<<endl<<source<<endl<<endl;//original text 
	cout<<"compressed:"<<endl<<content<<endl<<endl;//compressed text 
	cout<<"decompressed:"<<endl<<Decompress(compressed_content)<<endl<<endl;
	cout<<endl;
	cout<<"original size:"<<source.size()<<endl;
	cout<<"compressed size:"<<content.size()<<endl;
	return 0;
} 


图片来自:http://blog.csdn.net/abcjennifer/article/details/7995426



  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值