输入N个数,输出全部可能的排列组合(6+个小时啊耶稣~)

输入N个数,输出所有可能的排列组合(6+个小时啊,耶稣~)

输入N个数,输出所有可能的排列组合


          一行代码一行泪。。。手都被发热的笔记本烤的不舒服了。。。。6个多小时过去鸟。。。终于粗来鸟。。。。

昨天同学问到一个排列组合的问题,本身不会很难,原题是固定输入4个数字,例如1 2 3 4,输出所有可能的排列组合

暴力的话应该不难的。代码+debug,半个小时。

如果是输入N个数字呢?



先说简单的暴力方法,如果输入4个数字,输出所有的排列组合

代码比较短,也比较简单,没有很刻意的去把代码的风格写的好一点,所以数字常量什么的表介意。。。。

/**********************************************************************
code writer : EOF
code date :2014.06.11
e-mail : jasonleaster@gmail.com
code purpose:
        just for fun...
************************************************************************/
#include <stdio.h>

void fun(void);

int main()
{
        fun();

        return 0;
}

void fun(void)
{
        int array[4];
        int buffer[4];

        int temp = 0;

        int circle_1 = 0;
        int circle_2 = 0;
        int circle_3 = 0;
        int circle_4 = 0;

        printf("Hey,guys! Please input four numbers\n");

        //Input four number .
        for(temp = 0;temp < 4;temp++)
        {
                while(!scanf("%d",&array[temp]))

        for(temp = 0;temp < 4;temp++)
        {
                while(!scanf("%d",&array[temp]))
                {
                        while(getchar() != '\n')
                        {
                        }
                        printf("Input again and make sure the input data is right.\n");
                }
        }

        for(circle_1 = 0;circle_1 < 4;circle_1++)
        {
                buffer[0] = array[circle_1];

                for(circle_2 = 0;circle_2 < 4;circle_2++)
                {
                        if(array[circle_2] != array[circle_1])
                        {

                                buffer[1] = array[circle_2];

                                for(circle_3 = 0;circle_3 < 4;circle_3++)
                                {
                                        if(array[circle_3] != array[circle_2] && array[circle_3] != array[circle_1])
                                        {

                                                buffer[2] = array[circle_3];

                                                for(circle_4 = 0;circle_4 < 4;circle_4++)
                                                {
                                                        if(array[circle_4] != array[circle_3] &&
                                                           array[circle_4] != array[circle_2] &&
                                                           array[circle_4] != array[circle_1])
                                                        {
                                                                buffer[3] = array[circle_4];

                                                                for(temp = 0;temp < 4;temp++)
                                                                {
                                                                        printf("%d ",buffer[temp]);
                                                                }
                                                                printf("\n");
                                                        }
                                                }
                                        }
                                }
                        }
                }
        }
}


可以看出这里嵌套的for循环层数是取决于等待排列的数据的个数的,开销相当的大。

如果输入N个数字,输出所有的排列组合,这种方法是不可行的。

测试结果:

ubuntu2@ubuntu:~/Desktop$ ./a.out
Hey,guys! Please input four numbers
1 2 3 4
1 2 3 4
1 2 4 3
1 3 2 4
1 3 4 2
1 4 2 3
1 4 3 2
2 1 3 4
2 1 4 3
2 3 1 4
2 3 4 1
2 4 1 3
2 4 3 1
3 1 2 4
3 1 4 2
3 2 1 4
3 2 4 1
3 4 1 2
3 4 2 1
4 1 2 3
4 1 3 2
4 2 1 3
4 2 3 1
4 3 1 2
4 3 2 1



利用递归。。。。做出n的版本。

/****************************************************************
code writer : EOF
code date : 2014.06.12
e-mail:jasonleaster@gmail.com
code purpose:
	It's a hard time to finished this program but everthing is
Ok...It was here.
	Just change the macro ARRAYSIZE into the number of input
variable.This program would process it and print out all combination
of your input.

****************************************************************/
#include <stdio.h>

#define ARRAYSIZE 3
#define USED   1
#define UNUSED 0

struct location
{
	/*
	* There is a trick that we put the array into a structure.
	* What's happend? Why do we have to do this?
	* If you can't answer that questions, you may program without this trick and 
	* you will thank god "It helps me a lot..."
	*/
	int state[ARRAYSIZE];
	
	/*
	* We could pass this object as individual unit.
	* You need not to warry about problem make you sad when you are using pointer.
	* It would gone like a normal type variable. All in all, It's a very useful trick.
	*/
};

int buffer[ARRAYSIZE];//Deliberately,I used global varibles.This "buffer" array would be used as a buffer for printing out
int array[ARRAYSIZE];//Deliberately,I used global varibles. This "array" array would be used as a buffer for original inputed date

int  check(int depth,struct location current_state);//Prototype for function check
void fun(void);//Aha ...just like a puppet...

int main()
{
	fun();
	
	return 0;
}

void fun(void)
{
	int temp = 0;

	struct location initial_state;//structure for memory initial location state

	//input original data
	for(temp = 0;temp < ARRAYSIZE;temp++)
	{
		while(!scanf("%d",&array[temp])) // error check...I like it...useful and safe.
		{
			while(getchar() != '\n')
			{
			}
			printf("Input error\nPlease input agina!");
		}
	}

	//initialization
	for(temp = 0;temp < ARRAYSIZE;temp++)
	{
		buffer[temp] = 0;
		initial_state.state[temp] = UNUSED;
	}

	printf("\n\n");

	//Game start!
	check(ARRAYSIZE-1,initial_state);
}

int  check(int depth,struct location current_state)
{
/*
local varible description:

	depth: It is used for current depth of recursion.
	current_state: It is used for which location have alread been used.

If we have eight inputed variables.

---> depth decrese in this direction

location one   1 0 0 0 0 0 0 0
     ...
location four  0 0 0 1 0 0 0 0
location five  0 0 0 0 1 0 0 0
     ...
location eight 0 0 0 0 0 0 0 1

It would print out follow this location, if the current_state structure is like that.

*/
	int temp = 0;
	int foo  = 0;
	int last_location = -1;//used for saving the location which this data putted into

	if(depth > 0)
	{
		for(foo = 0;foo < ARRAYSIZE ;foo++)//try to use different possible location.
		{		
			for(temp = 0;temp < ARRAYSIZE ;temp++)//find a location for current data.
			{
				if(temp <= last_location)
				{
					continue;//jump over the location where the data have been putted.
				}

				if(current_state.state[temp] == UNUSED)//If this location is empty, we could use it for current data.
				{
					current_state.state[temp] = USED;//Don't forget to change current state into "USED".
					last_location = temp;//save current location into last_location 
					buffer[ARRAYSIZE-(depth+1)] = array[temp];//It's time to put the data input buffer
					check(depth-1,current_state);
					current_state.state[last_location] = UNUSED;//clear used location and prepare for depth recursion.
					break;//We have found a empty location for current data so break out.
				}
			}
			
		}
	}
	else if(depth == 0)//If we touch the deepest floor, it's time to print out all data in buffer.
	{
		for(temp = 0;temp < ARRAYSIZE ;temp++)//check which location was left for the last one data.
		{

			if(current_state.state[temp] == UNUSED)
			{
				current_state.state[temp] = USED;
				last_location = temp;
				buffer[ARRAYSIZE-(depth+1)] = array[temp];
				break;
			}
		}

		for(temp = 0;temp < ARRAYSIZE;temp++)//Needless to describle what's happend in this loop....haha...
		{
			printf("%d ",buffer[temp]);
		}
		printf("\n");
	}
}

ubuntu2@ubuntu:~/Desktop$ ./a.out
1 2 3


1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1



                check(depth-1,current_state);的位置非常关键,而且这里把数组放进结构体是故意的,利用结构体可以直接赋值的性质,并且规避掉数组传参实质是传指针的性质,防止递归层数据之间相互影响。


其实这种排列组合只要稍加限制,可以和八皇后问题联系起来



输入N个数,输出全部可能的排列组合(6+个小时啊耶稣~)