字符数组的压缩程序

      周六,小雨,写个字符压缩代码,来玩一下。

      压缩示例:

a b b c c c d e e 
a b 2 c 3 d e 2 

a b b c c c d e f 
a b 2 c 3 d e f 




a b 
a b 

a a 
a 2 

a a a 

a 3 

 

    代码:

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

int compress(char *a,  int nSize)  
{
	assert(a != NULL && nSize > 0);
  	char *p = new char[nSize];
	assert(p != NULL);
	
    int i = 0;
  	int j = 0;
    int iTimes = 0;
    for(i = 0; i < nSize - 1; ++i)  // 下面有a[i + 1],故需要防止越界
    {
    	if(a[i] != a[i + 1]) // 说明遇到了新字符a[i + 1], 该终止旧的了,退出累计
        {
            if(iTimes > 0)   // 旧字符有iTimes+1个,要赋值了
            {
              	p[j++] = a[i];
                p[j++] = iTimes + 1 + '0';
            	iTimes = 0;
            }
            else // 旧字符a[i]的个数仅仅是1个,直接赋值
            {
            	p[j++] = a[i];
            }
        }
        else // 相等,则记录次数
        {
            ++iTimes;

            if(i == nSize - 2)  // 相等的情况,如果持续到最后两个字符,则需要退出了, 否则没机会退出了(无下一次循环)
			{
				p[j++] = a[i];
				p[j++] = iTimes + 1 + '0';
			}
        }
    }

    if(1 == nSize)     	// 元素个数为1时,不会走上述遍历,故单独处理
    {
    	p[j++] = a[0];
    }

    if(nSize > 1  &&  a[nSize - 2] != a[nSize - 1])   // 最后两个元素不相等时,最后一个元素需要补上
    {
    	p[j++] = a[nSize - 1];
    }
  
    nSize = j;
    memcpy(a, p, nSize);

    delete [] p;   	// 不是delete p啊
    p = NULL;
  
    return nSize;
}

void print(char a[], int n)
{
	int i = 0;
	for(i = 0; i < n; ++i)
	{
		printf("%c ", a[i]);
	}

	printf("\n");
}


void test1()
{
	char a[] = {'a', 'b',  'b', 'c', 'c', 'c', 'd', 'e', 'e'};
	int nSize = sizeof(a) / sizeof(a[0]);
	print(a, nSize);
	int nRet = compress(a, nSize);
	print(a, nRet);
	printf("\n");
}

void test2()
{
	char a[] = {'a', 'b',  'b', 'c', 'c', 'c', 'd', 'e', 'f'};
	int nSize = sizeof(a) / sizeof(a[0]);
	print(a, nSize);
	int nRet = compress(a, nSize);
	print(a, nRet);
	printf("\n");
}

void test3()
{
	char a[] = {'a'};
	int nSize = sizeof(a) / sizeof(a[0]);
	print(a, nSize);
	int nRet = compress(a, nSize);
	print(a, nRet);
	printf("\n");
}

void test4()
{
	char a[] = {'a', 'b'};
	int nSize = sizeof(a) / sizeof(a[0]);
	print(a, nSize);
	int nRet = compress(a, nSize);
	print(a, nRet);
	printf("\n");
}

void test5()
{
	char a[] = {'a', 'a'};
	int nSize = sizeof(a) / sizeof(a[0]);
	print(a, nSize);
	int nRet = compress(a, nSize);
	print(a, nRet);
	printf("\n");
}

void test6()
{
	char a[] = {'a', 'a', 'a'};
	int nSize = sizeof(a) / sizeof(a[0]);
	print(a, nSize);
	int nRet = compress(a, nSize);
	print(a, nRet);
}

int main()
{
	test1();
	test2();
	test3();
	test4();
	test5();
	test6();

	return 0;
}

     测了一下,结果OK.

 

     很显然, 这是压缩算法, 非膨胀操作, 故可以采用就地算法(原地算法), 如下:

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

int compress(char *a,  int nSize)  
{
	assert(a != NULL && nSize > 0);

	int flag = 0;
	if(nSize > 1 && a[nSize - 2] != a[nSize - 1])  // a[nSize - 2]可能会被破坏,导致后续的比较出现问题,所以,这里先比较
	{
	   flag = 1;
	}

    int i = 0;
  	int j = 0;
    int iTimes = 0;
    for(i = 0; i < nSize - 1; ++i)  // 下面有a[i + 1],故需要防止越界
    {
    	if(a[i] != a[i + 1]) // 说明遇到了新字符a[i + 1], 该终止旧的了,退出累计
        {
            if(iTimes > 0)   // 旧字符有iTimes+1个,要赋值了
            {
              	a[j++] = a[i];
                a[j++] = iTimes + 1 + '0';
            	iTimes = 0;
            }
            else // 旧字符a[i]的个数仅仅是1个,直接赋值
            {
            	a[j++] = a[i];
            }
        }
        else // 相等,则记录次数
        {
            ++iTimes;

            if(i == nSize - 2)  // 相等的情况,如果持续到最后两个字符,则需要退出了, 否则没机会退出了(无下一次循环)
			{
				a[j++] = a[i];
				a[j++] = iTimes + 1 + '0';
			}
        }
    }

    if(1 == nSize)     	// 元素个数为1时,不会走上述遍历,故单独处理
    {
    	a[j++] = a[0];
    }

    if(1 == flag)   // 最后两个元素不相等时,最后一个元素需要补上
    {
    	a[j++] = a[nSize - 1];
    }
  
    nSize = j;

    return nSize;
}

void print(char a[], int n)
{
	int i = 0;
	for(i = 0; i < n; ++i)
	{
		printf("%c ", a[i]);
	}

	printf("\n");
}


void test1()
{
	char a[] = {'a', 'b',  'b', 'c', 'c', 'c', 'd', 'e', 'e'};
	int nSize = sizeof(a) / sizeof(a[0]);
	print(a, nSize);
	int nRet = compress(a, nSize);
	print(a, nRet);
	printf("\n");
}

void test2()
{
	char a[] = {'a', 'b',  'b', 'c', 'c', 'c', 'd', 'e', 'f'};
	int nSize = sizeof(a) / sizeof(a[0]);
	print(a, nSize);
	int nRet = compress(a, nSize);
	print(a, nRet);
	printf("\n");
}

void test3()
{
	char a[] = {'a'};
	int nSize = sizeof(a) / sizeof(a[0]);
	print(a, nSize);
	int nRet = compress(a, nSize);
	print(a, nRet);
	printf("\n");
}

void test4()
{
	char a[] = {'a', 'b'};
	int nSize = sizeof(a) / sizeof(a[0]);
	print(a, nSize);
	int nRet = compress(a, nSize);
	print(a, nRet);
	printf("\n");
}

void test5()
{
	char a[] = {'a', 'a'};
	int nSize = sizeof(a) / sizeof(a[0]);
	print(a, nSize);
	int nRet = compress(a, nSize);
	print(a, nRet);
	printf("\n");
}

void test6()
{
	char a[] = {'a', 'a', 'a'};
	int nSize = sizeof(a) / sizeof(a[0]);
	print(a, nSize);
	int nRet = compress(a, nSize);
	print(a, nRet);
}

int main()
{
	test1();
	test2();
	test3();
	test4();
	test5();
	test6();

	return 0;
}

       测了一下, 结果OK.

 

       作为程序员, 尽可能考虑到各种性能, 并处理好各种边界和异常, 很重要。

 

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值