1. 程式人生 > >基因資料壓縮演算法(ACTG) C++

基因資料壓縮演算法(ACTG) C++

        基因資料壓縮演算法是一個初級的資料壓縮演算法,基因資料如下所示"ATAGATGCAT",如果使用標準的ASCII編碼(每個字元1個位元組),這個基因字串的流長度是10*8=80位。

        這些字元是由4種不同的字元組成,所有我們可以使用雙位編碼壓縮,比如 A:00, C:01, T:10, G11,壓縮之後我們就可以在一個位元組存放4個基因字元了,當資料比較大時,壓縮效率為25%。

完整程式碼

#include <iostream>
#include <string>
using namespace std;

void PrintBits(const char *pstr, int width = 1);

// ACTG A:00, C:01, T:10, G11
class Dna
{
public:
	Dna() : sizes(0) {}
	Dna(const char *str);

	void AddCompress(const char c) { Compress(c); }
	void AddCompress(const char *pstr);
	string Expand();

	int Size() const { return sizes; }
	string Data() const { return data; }
	string Compress() const { return compressData; }
	void PrintCompressData() { PrintBits(compressData.c_str()); }
	void PrintCompressData(int width) { PrintBits(compressData.c_str(), width); }

private:
	int sizes;	// 存放資料數
	string data;	// 存放原始資料
	string compressData; // 存放壓縮後的二進位制資料

	void Compress(const char c);
	unsigned char Index(char c);
	char Table(int index) const;
	void PrintBits(const char c);
	void PrintBits(const char *pstr, int width = 1);
};

int main(void)
{
	char str[] = "ACTG";

	Dna dna(str);

	cout << dna.Size() << endl;
	cout << dna.Expand() << endl;

	dna.AddCompress("GTCA");
	cout << dna.Size() << endl;
	cout << dna.Expand() << endl;

	dna.PrintCompressData();

	system("pause");
	return 0;
}

Dna::Dna(const char *str) : sizes(0)
{
	if (str)
	{
		const char *p = str;

		while (*p)
		{
			Compress(*p);
			p++;
		}
	}
}

void Dna::AddCompress(const char *pstr)
{
	if (!pstr)
		return;

	const char *p = pstr;
	while (*p)
	{
		Compress(*p);
		p++;
	}
}

// class Dna private scope

// 壓縮字元c,並新增到compressData中
void Dna::Compress(const char c)
{
	data.append(1, c);

	if (sizes % 4 == 0)
		compressData.append(1, '\0');

	int n = sizes % 4;
	
	compressData[sizes / 4] |= Index(c) << (6 - 2 * n);
	sizes++;
}

// 解壓縮,並以string返回
string Dna::Expand()
{
	string s;

	for (int i = 0; i < sizes; i++)
	{
		int n = i % 4;
		unsigned char index = ((unsigned char)compressData[i / 4]) >> (6 - 2 * n);
		s.append(1, Table(index));
	}
	return s;
}

// 根據char值返回對應的索引,比如'A'為0時返回0
unsigned char Dna::Index(char c)
{
	if (c == 'A')
		return 0;
	else if (c == 'C')
		return 1;
	else if(c == 'T')
		return 2;
	else // if(c == 'G')
		return 3;
}

// 根據index值返回對應的字元,比如index為0時返回'A'
char Dna::Table(int index) const
{
	static char table[4] = { 'A', 'C', 'T', 'G' };
	return table[index % 4];
}

void Dna::PrintBits(const char c)
{
	for (int i = 0; i < 8; i++)
	{
		if ((c << i) & 0x80)
			cout << '1';
		else
			cout << '0';
	}
}

void Dna::PrintBits(const char *pstr, int width)
{
	if (!pstr)
		return;

	const char *p = pstr;
	int nums = 0;

	while (*p)
	{
		PrintBits(*p);
		p++;
		
		if (!((++nums) % width))
			cout << endl;
	}
	cout << endl;
}
輸出結果為:


參考

       《演算法》 第四版 5.5 資料壓縮