一种基于插入思想的求全排列算法

插入函数:

char** insert(char*a, char character_cnt, char chara)
{
	char** ret = new char*[character_cnt + 1];
	int copy_pre;

	for (int i = 0; i < character_cnt + 1; i++)
		ret[i] = new char[character_cnt + 1];

	for (int i = 0; i < character_cnt + 1; i++) //character_cnt+1个待插位置,对应[O before],[1 before]…[character_cnt-1 before]
	{
		for (copy_pre = 0; copy_pre < i; copy_pre++)
			ret[i][copy_pre] = a[copy_pre];
	
		int a_copy_after_start = copy_pre;
		
		ret[i][copy_pre] = chara;
		
		copy_pre++;
		for (; a_copy_after_start < character_cnt; a_copy_after_start++, copy_pre++)
			ret[i][copy_pre] = a[a_copy_after_start];
	}

	return ret;
}

求全排列:

char** f(char* a,int character_cnt)
{
	int tmp = 1, out_pos = 0, sum = 0;
	int* stdOFFSET = new int[character_cnt];
	
	//k=1 k=2
	stdOFFSET[0] = 0;
	stdOFFSET[1] = 0;

	for (int i = 2; i < character_cnt; i++) //k=3… character_cnt
	{
		int mul = 1;
		for (int j = 1 ; j <= i ; j++) mul *= j;
		sum += mul;
		stdOFFSET[i] = sum;
	}
	///
	int tmpsum = 0;
	for (int i = 1; i <= character_cnt; i++) //1 2 3 4
	{
		int mul = 1;
		for (int j = 2; j <= i; j++)
			mul *= j;

		tmpsum += mul;
	}

    char** p = new char*[tmpsum - 1];
	for(int i = 0; i < tmpsum; i++)
	{
		p[i] = new char[character_cnt+1]; 
		memset(p[i], 0, sizeof(*p[i])*character_cnt+1);
	}
	//
	
	p[0][0] = a[0];
	for (int k = 1 ; k < character_cnt ; k++)  //从两位字符开始
	{
		for (int m = 0; m < tmp; m++)
		{
			char** pout = insert(p[m + stdOFFSET[k - 1]], k, a[k]);
			for (int j = 0; j < k + 1; j++)
				memcpy(p[out_pos++], pout[j], k + 1);
		}
		tmp *= (k + 1); //2->6->24,分裂后个数
	}
	return p + out_pos;
}

 测试代码:

int _tmain(int argc, _TCHAR* argv[])
{
    char A[]={"abcdefgh"};

	char** x = f(A,strlen(A));    //x指向计算结果的最后位置

	for (int i = 1*2*3*4*5*6*7*8; i > 0 ; i--)
		cout << 1*2*3*4*5*6*7*8-i << " : " << *(x-i) << endl;

}

基本思想为依次从字符串中取数,每取一个数,往现有计算结果的各个位置插入,无需迭代,易于理解

但与递归法求全排列相比,需要消耗一定的堆空间。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值