使用回溯法求所有从n个元素中取m个元素的组合

包含2个版本,第一个为递归版本,代码简洁,性能稍差。第二个为迭代版本,逻辑复杂,但性能更好。

 

#include 
#include 
//#include 

typedef char ELE_TYPE;
#define ELE_FMT "%c"

//int g_count=0;

//元素类型和格式符号使用宏定义,很容易改为其他数据类型,如数组类型改为int,则格式符改为"%d ".
void printCombo(int idx_arr[], ELE_TYPE eArr[],int m)
{
    int i;
	//g_count++;
	//return ;
	for (i=0;i n-m+i,则为超限

// 这个子程序用到5个if和一个while,总共6次比较,显然,其逻辑要比上面的那个递归版本复杂的多。
// 凡事有利就有弊,这个子程序的性能要比上面的递归版本好,
// 我的试验表明,将输出子程序printCombo改为只做一次整数加法,当n=28,m=14,迭代版本的性能是递归版本的130%

#define M_FILL 0   //填充模式
#define M_INC  1   //递增模式

void IterativeCombos(int n, int m, int idx_arr[], ELE_TYPE eArr[] )
{
	int i=0;  
	int mode=M_FILL;
	
	while (i>=0)
	{
		if (mode==M_FILL)	//填充模式
		{
			if (i==0)
				idx_arr[0]=0;
			else
				idx_arr[i] = idx_arr[i-1]+1;
			
			if (i == m-1)	//当前焦点已经达到最大深度
			{
				printCombo(idx_arr,eArr,m); //打印这个包含m个元素的组合
				mode=M_INC;	//切换为增量模式	
			}
			else			//没有达到最大深度
				i++;		//继续填充下级节点
		}
		else				//增量模式
		{
			idx_arr[i]++;	//焦点元素递增
			
			if ( idx_arr[i] > n-m+i ) //已经超限
				i--;
			else
			{
				if (i==m-1)		//当前焦点已经达到最大深度
					printCombo(idx_arr,eArr,m); //打印这个包含m个元素的组合
				else
				{
					i++;		 //继续填充下级节点
					mode=M_FILL; //切换到填充模式
				}
			}
		}
	}
}

int main(int argc, char* argv[])
{
    int i;

#define N  6
#define M  3

    ELE_TYPE eArr[N]; //定义6个数组的数组,
    int idx_arr[M];   //取到的3个元素的需要放在数组idx_arr中

	for (i=0;i


 

你可能感兴趣的:(递归,回溯,算法)