全排列

来源:互联网 发布:淘宝开店怎样推广 编辑:程序博客网 时间:2024/05/10 15:09

全排列:

非递归算法:解题思路因为自己都讲不清楚。但觉得这位网友讲的不错把他的就直接引用了,至于代码我自己已经修改编译通过了!

题目:1~n的全排列

思想:(字典序法)初始化数组为1,2,3,...,n作为开端;设法从后续排列中找到大于前次结果但小于其他结果的序列;依此找出这样的序列(后面序列肯定大于前面序列),则最后一个序列肯定是n,...,3,2,1
步骤:

·  假设情景:找“*243”该序列的下一个后续序列

·  从后往前找,找到这样一个数,它后面的数更大,(即找到"*24*",取2作为当前数,下标为i

·  “2”的后面,找到最接近2且比2大的数,这里找到“3”(下标为j

·  调换a[i]a[j]的值

·  a[i+1]……a[n-1]进行转置

·  此时数组a中的数就是所求后续序列

·  1,2,3,...,n依此求出后续序列(即重新进行上面步骤),一直找到i=0a[0]>a[1]则算法结束,全排列已全部给出。

三思:

·  怎么保证后面的序列比前面的大?首先开端是序列中最小的,i后面的部分是倒叙排列的,在对调(保证了大于前面序列)后,对i后面的进行逆置,保证了自身是后续排列中最小的,所以小于前面大于后面,依此递增,直到n,...,3,2,1算法结束。

·  该算法要给一个开端,对于求“142”全排列这种情况,是不是还需要进行先排序得到“124”后再处理?

·  该算法对调操作频繁,还有转置操作,相比较于递归调用函数,时间更少了,但心里不是滋味。

·  处理"1223"这种情况又怎样?递归方法不能处理,但这种方法可以处理。

·  对于字符排序"abc","abb"这两种情况,貌似与数字排序"123","122"一样,反正字符也可以比较大小,所以这两种情况也可以得到解决。

 

//全排列非递归算法

#include<stdio.h>

#define N 20

void Init_Arry(intarr[],int n);    //初始化数组

void Print(intn);            //输出排列

void Swap(inti,int j);       //交换arr[i]和arr[j]的值

void Tranpose(intk,int m);   //把数组脚标k到m的转置

int  Full_Arry(int n);        //对n个数进行全排列

int arr[N];

int count=0;                  //排列的个数

int main()

{

       int n;

       printf("\t全排列\n\n");

       printf("输入数字的个数(1~20):\n");

       scanf("%d",&n);

       while(n>20||n<0)

       {

              printf("输入数字不合法,请重新输入(1~20):\n");

          scanf("%d",&n);

       }

    Init_Arry(arr,n);

       Full_Arry(n);

 

       return 0;

}

//初始化数组

void Init_Arry(intarr[],int n)

{

       int i;

       for(i=1;i<=n;i++)

              arr[i]=i;

}

//输出排列

void Print(int n)

{

       int i;

       count++;

       printf("(%2d) ",count);

       for(i=1;i<=n;i++)

              printf("%d ",arr[i]);

       printf("\n");

}

//交换arr[i]和arr[j]的值

void Swap(inti,int j)

{

       int temp;

       temp=arr[i];

       arr[i]=arr[j];

       arr[j]=temp;

}

//把数组脚标k到m的转置

void Tranpose(intk,int m)

{

       int i,j;

       for(i=k,j=m;i<=(k+m)/2;j--,i++)

              Swap(i,j);

}

//对n个数进行全排列

int Full_Arry(intn)

{

       int i,j;

       if(n==1)                     //n=1时

       {

              Print(n);

              return 1;

       }

       else if(n==2)

       {

              printf("(1) %d%d\n",1,2);

              printf("(2) %d%d\n",2,1);

              return 1;

       }

       else

              while(1)

              {

                     Print(n);

            for(i=n-1;i>=1;i--)      //n必须大于等于2

                     {

                         if(arr[i]<arr[i+1])  //先求i

                                break;

                if(i==1)

                                return 1;        //函数出口:当i=1且arr[1]>arr[2]时,函数结束

                     }

            for(j=n;j>i;j--)         //后求j

                     {

                if(arr[i]<arr[j])    //

                                break;

                     }

            Swap(i,j);               //调换arr[i]与arr[j]的值

            Tranpose(i+1,n);         //把i后面的数转置

              }

}

 

递归的思路就不给出了;

//递归算法

 //全排列递归算法

#include<stdio.h>

#define N20

voidInit_Arry(int arr[],int n);               //初始化数组

voidarrange_all(int size, int arr[], int pos);      //size   要排列的数据个数  

                                                //arr[]   排列存放的数组  

                                               //pos     当前排列位置 

voidPrint(int n);                             //输出排列                                               

intarr[N];

intcount=0;                                    //排列的个数

intmain()

{

       int n;

       printf("\t全排列\n\n");

       printf("输入数字的个数(1~20):\n");

       scanf("%d",&n);

       while(n>20||n<0)

       {

              printf("输入数字不合法,请重新输入(1~20):\n");

          scanf("%d",&n);

       }

    Init_Arry(arr,n);

       arrange_all(n, arr, 1);

       return 0;

}

//初始化数组

voidInit_Arry(int arr[],int n)

{

       int i;

       for(i=1;i<=n;i++)

              arr[i]=i;

}

//输出排列

voidPrint(int n)

{

       int i;

       count++;

       printf("(%2d) ",count);

       for(i=1;i<=n;i++)

              printf("%d ",arr[i]);

       printf("\n");

}

voidarrange_all(int size, int arr[], int pos) 

{

     inti, temp; 

     if (pos==size) //经排到最后

        {

         Print(size, arr); 

     }else

               for (i=pos;i<=size; i++) // 对当前位置后的所有位置排列

        {

         temp = arr[pos]; // 交换位置

         arr[pos] = arr[i]; 

         arr[i] = temp; 

         // 递归继续后面的调用 

         arrange_all(size, arr, pos + 1); 

         // 在交换回来保持原有次序

         temp = arr[pos]; 

         arr[pos] = arr[i]; 

         arr[i] = temp; 

     }

}

 (算法代码参考互联网)

吴德妙 2011-11-26

0 0
原创粉丝点击