全排列算法的理解

来源:互联网 发布:python内存管理机制 编辑:程序博客网 时间:2024/06/05 07:38

(1)序数法:

   因为: (2)字典序法:

n!=((n-1)+1)(n-1)!=(n-1)(n-1)!+(n-1)!,

同理

(n-1)!=(n-2)(n-2)!+(n-2)!,

…,

n!= (n-1)(n-1)!+ (n-2)(n-2)!+…+2*2!+2!

不难证明0n!-1的任何数m可唯一的表示为 m=an-1(n-1)!+ an-2(n-2)!+…+a11!, 其中
0< ai< i.
 

   

 

 

生成给定全排列的下一个排列

所谓一个的下一个就是这一个

下一个之间没有其他的。这就要求这一个与下一个有尽可能长的共同前缀,也即变化限制在尽可能短的后缀上。

(3)换位法:

生成n!可以在生成(n-1)!的阶乘基础上,依次从最右端插入第n个数。

考虑{1,2…n}的一个排列,其上每一个整数都给了一个方向,我们称整数k是可移的(Mobile&Active),如果它的箭头所指的方向的邻点小于它本身。

 

于是,我们可由

按如下算法产生所有排列

算法

1开始时:

2,当存在可移数时

(a)找最大的可移数m
(b)m与其箭头所指的邻数互换位置
(c)将所得排列中比m大的数p的方向调整,即改为相反方向。

算法如下

            m=m1,          0  m ≤n!-1

      m1=2m2+k1,     0≤ k1 ≤1

      m2=3m3+ k2,     0≤ k2 ≤2

       …………….

           mn-2=(n-1)mn-1+ kn-2, 0≤ kn-2 ≤n-2

      mn-1= kn-1,         0≤ kn-1 ≤n-1

  (kn-1 k2k1) ←→ m

(5)逐渐增大法。

 描述:要使序列从小到大排序。就是要使每一个序列的前缀尽可能多的相同。通过不断使后面的位数的逆序数达到最大话。来不段使序列,增大。

Code List::

////  author Jian  ///////

int permute(int a[])

{

 int sou[N],i,j;       

  for(i=0;i<N;i++)

     if(a[i]>a[i+1]) break;

    if(i==N-2) return 0;

    for(i=0;i<N;i++) sou[i]=a[i];

    for(i=N-2;i>=0;i++)  if(sou[i]<sou[i+1]) break;

    for(j=N-1;j>i;j++)  if(sou[j]>sou[i]) break;

     a[i]=sou[j];

     sou[j]=sou[i];

      for(j=i+1;j<N;j++)

      a[j]=sou[N-j+i];

    return 1;

}

/////////////

#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#define MIN 100
typedef struct node
{
       int data;
       char direc;
       }node;
void print(int se[],int m)
{

                 
   
     }
void sequence(int n)
{
     char se[n],c,i,p,j;
     se[n-1]='/0';
     for(i=0;i<24;i++)
        {
           c=i;
           p=2;
            for(j=n-2;j>=0;j--)
             {
              
               se[j]=c%p+'0';
               c/=p;
               p++;                
             }    
              printf("%s/n",se); 
        }
     }
     void swap(node &m,node &n)
     {
          node temp;
           temp=m;
           m=n;
           n=temp;
          }
 void dic(int n)
 {
      char a[n+1],i,fac=24;
     
      int min,temp,j,c;
      a[n]='/0';
      for(i=0;i!=n;i++)
         a[i]=i+1+'0';
         printf("%s/n",a);
         while(--fac)
         {
           c=0;
            for(i=n-2;i!=-1;i--)
              if(a[i]<a[i+1])
                break;
                min=100;
              for(j=i+1;j!=n;j++)     
                      if(a[j]>a[i]&&a[j]<min)
                        {
                            c=j;
                        
                            min=a[j];                  
                        }
                      
               temp=a[c];
               a[c]=a[i];
               a[i]=temp;
            
               for(j=i+1;j<=(n+i)/2;j++)
               {
                  temp=a[j];
                  a[j]=a[n+i-j];
                  a[n+i-j]=temp;                    
               }
                 printf("%s/n",a);    
         }
        
     
      } 
      void changepos(int n)
      {
           node num[5];
           int i,max,temp,max1,maxdata;
           for(i=0;i<4;i++)
              {
                 num[i].data=i+1;
                 num[i].direc='l';            
              }
              num[4].data=MIN;
            while(1)
            {
                max1=-1;   
                for(i=0;i<4;i++)
                {
                  if((i&&num[i].direc=='l'&&num[i-1].data<num[i].data)||(num[i].direc=='r'&&num[i+1].data<num[i].data))
                    { 
                    if(num[i].data>max1)
                      {
                       max1=num[i].data;
                       max=i;
                       }
                    }            
                }
                maxdata=num[max].data;
               // printf("%d %c/n",max,num[max].direc);
                if(max1==-1) break;
                 if(num[max].direc=='r') swap(num[max],num[max+1]);
                 else swap(num[max-1],num[max]);
                   for(i=0;i<4;i++)
                      if(num[i].data>maxdata)
                        {
                          if(num[i].direc=='r')
                            num[i].direc='l';
                           else num[i].direc='r';                          
                        } 
                        for(i=0;i<4;i++)
                         printf("%d",num[i].data);
                         printf("/n");
                    }
          
           }
int main()
{
    double c=0.3;
    int n=4,m=5;
    //sequence(n);
   //dic(n);
   printf("%f",c/m);
    //changepos(n);
    system("pause");
   
    }