数据无损压缩编码——算术编码和译码(附有编码和译码的C++程序)

基本思想

用0到1之间的一个数值区间来表示字符,而不是为每一个需要编码的字符分配一个单独的编码(如霍夫曼编码)。输出时可以从该区间内选择出任意一个小数作为实际编码。

编码例题及程序

某字符序列含有a,b,c,d,e五个字符,输入为各个字符的出现概率,及需要编码的字符序列,输出为算术编码区间(保留小数点后10位)。
样例输入:

0.2 0.3 0.1 0.15 0.25
aaabded

样例输出:

0.0033640000
0.0033775000

程序代码:

// 程序名称:算术编码的区间输出
#include<iostream>
#include<iomanip>
using namespace std;

int main(void)
{
	//数据定义部分
	double p[5];       
	string origin_code;
	double cumsum_p[5] = { 0 };
	unsigned j(0);

	//数据输入部分
	for (unsigned i(0); i < 5; ++i)
	{
		cin >> p[i];
	}
	cin >> origin_code;

	//数据处理部分
	for (unsigned i(1); i < 5; ++i)
	{
		cumsum_p[i] = cumsum_p[i - 1] + p[i - 1];
	}
	unsigned slength = origin_code.length();
	double leftPole(0), rightPole(1);
	double RangeLength, tempLeft, tempRight;
	for (unsigned i(0); i < slength; ++i)
	{
		RangeLength = rightPole - leftPole;
		switch (origin_code[i])
		{
		case'a': {tempLeft = leftPole; tempRight = leftPole + cumsum_p[1] * RangeLength; break; }
		case'b': {tempLeft = leftPole + cumsum_p[1] * RangeLength; tempRight = leftPole + cumsum_p[2] * RangeLength; break; }
		case'c': {tempLeft = leftPole + cumsum_p[2] * RangeLength; tempRight = leftPole + cumsum_p[3] * RangeLength; break; }
		case'd': {tempLeft = leftPole + cumsum_p[3] * RangeLength; tempRight = leftPole + cumsum_p[4] * RangeLength; break; }
		case'e': {tempLeft = leftPole + cumsum_p[4] * RangeLength; tempRight = rightPole; break; }
		}
		leftPole = tempLeft;
		rightPole = tempRight;
	}

	//结果输出部分
	cout << fixed << setprecision(10) << leftPole << endl << fixed << setprecision(10) << rightPole ;

	return 0;
}

译码例题及程序

对于由a,b,c,d,e 5个符号组成的符号序列,输入各符号的出现概率及其算术编码,输出译码后的符号,符号长度是10位。
样例输入:

0.2 0.3 0.1 0.15 0.25
0.0033713425

样例输出:

aaabdedcbc

程序代码:

//程序名称:算术编码译码程序
#include<iostream>
using namespace std;

int main(void)
{
	//数据定义部分
	double p[5];
	double code;
	double leftPoles[5];
	double rightPoles[5];
	string code_elements = "abcde";
	string Translate_code;
	unsigned time(0);

	//数据输入部分
	for (unsigned i=0; i < 5; ++i)
	{
		cin >> p[i];
	}
	cin >> code;

	//数据处理部分
	for (unsigned j=0; j < 5; ++j)
	{
		if (j == 0)
		{
			leftPoles[j] = 0;
			rightPoles[j] = p[0];
		}
		else if (j == 4)
		{
			leftPoles[j] = 1 - p[4];
			rightPoles[j] = 1;
		}
		else
		{
			leftPoles[j] = leftPoles[j - 1] + p[j - 1];
			rightPoles[j] = rightPoles[j - 1] + p[j];
		}
	}
	while (code != 1&&time++<10)
	{
		for (unsigned k(0); k < 5; ++k)
		{
			if (leftPoles[k] <= code && code < rightPoles[k])
			{
				Translate_code += code_elements[k];
				code = (code - leftPoles[k]) / (rightPoles[k] - leftPoles[k]);
				break;
			}
		}
	}

	//结果输出部分
	cout << Translate_code << endl;

	return 0;
}
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值