全排列问题(递归算法) 汇总

一。全排列是将一组数按一定顺序进行排列,如果这组数有n个,那么全排列数为n!个。现以{1, 2, 3, 4, 5}为
例说明如何编写全排列的递归算法。

1、首先看最后两个数4, 5。 它们的全排列为4 5和5 4, 即以4开头的5的全排列和以5开头的4的全排列。
由于一个数的全排列就是其本身,从而得到以上结果。
2、再看后三个数3, 4, 5。它们的全排列为3 4 5、3 5 4、 4 3 5、 4 5 3、 5 3 4、 5 4 3 六组数。
即以3开头的和4,5的全排列的组合、以4开头的和3,5的全排列的组合和以5开头的和3,4的全排列的组合.
从而可以推断,设一组数p = {r1, r2, r3, ... ,rn}, 全排列为perm(p),pn = p - {rn}。
因此perm(p) = r1perm(p1), r2perm(p2), r3perm(p3), ... , rnperm(pn)。当n = 1时perm(p} = r1。
为了更容易理解,将整组数中的所有的数分别与第一个数交换,这样就总是在处理后n-1个数的全排列。

算法如下:

#include <stdio.h>  

int n = 0;  

void swap(int *a, int *b) 
{     
    int m;     
    m = *a;     
    *a = *b;     
    *b = m; 
}  
void perm(int list[], int k, int m) 
{     
    int i;     
    if(k > m)     
    {          
        for(i = 0; i <= m; i++)             
            printf("%d ", list[i]);         
        printf("\n");         
        n++;     
    }     
    else     
    {         
        for(i = k; i <= m; i++)         
        {             
            swap(&list[k], &list[i]);             
            perm(list, k + 1, m);             
            swap(&list[k], &list[i]);         
        }     
    } 
} 
int main() 
{     
    int list[] = {1, 2, 3, 4, 5};     
    perm(list, 0, 4);     
    printf("total:%d\n", n);     
    return 0; 
}  



 

问题描述:
R={r1,r2,…,rn}是要进行排列的n个元素,Ri=R-{ri}。
集合X中元素的全排列记为perm(X)。
(ri)perm(X)表示在全排列perm(X)的每一个排列前加上前缀得到的排列。R的全排列可归纳定义如下:
n=1时,perm(R)=(r),其中r是集合R中唯一的元素;
n>1时,perm(R)由(r1)perm(R1),(r2)perm(R2),…,(rn)perm(Rn)构成。
依此递归定义,可设计产生perm(R)的递归算法及测试(驱动)程序(和结果)如下:
————————————————————————————————————————————————
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
template <class T>
void perm(T list[], int k, int m)
{//产生list[k:m]的所有排列
 if (k==m)
 {//单元素排列
  for (int i=0; i<=m; i++)
   cout << setw(5) << list[i];
  cout << endl;
 }
 else
 {//多元素序列,递归产生排列
  for (int i=k; i<=m; i++)
  {
   swap(list[k],list[i]);
   perm(list,k+1,m);
   swap(list[k],list[i]);
  }
 }
}
void main()
{
 string list[10] = { "x0","x1","x2","x3"};//,"x4","x5","x6","x7","x8","x9"};
 perm(list,0,3);
}
// result
   x0   x1   x2   x3
   x0   x1   x3   x2
   x0   x2   x1   x3
   x0   x2   x3   x1
   x0   x3   x2   x1
   x0   x3   x1   x2
   x1   x0   x2   x3
   x1   x0   x3   x2
   x1   x2   x0   x3
   x1   x2   x3   x0
   x1   x3   x2   x0
   x1   x3   x0   x2
   x2   x1   x0   x3
   x2   x1   x3   x0
   x2   x0   x1   x3
   x2   x0   x3   x1
   x2   x3   x0   x1
   x2   x3   x1   x0
   x3   x1   x2   x0
   x3   x1   x0   x2
   x3   x2   x1   x0
   x3   x2   x0   x1
   x3   x0   x2   x1
   x3   x0   x1   x2
Press any key to continue
————————————————————————————————————————————————
算法perm(list,k,m)递归地产生所有前缀是list[0:k-1],且后缀是list[k:m]的全排列的所有排列。 函数调用perm(list,0,n-1)则产生list[0:n-1]的全排列。
 
三、

现在有一个列表,需要将列表第K个到第M个元素进行全排列,并且输出。

 基本思想:

(一) 当K=M时,即待排序列不存在时,直接输出0到M项的值。

(二) 当K>M时,依次将序列中每一个元素排到第K位,然后再全排K+1到M项。

算法如下:

protected void Button1_Click(object sender, EventArgs e)
        {
            List<int> list = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            Perm(list, 5, 8);
        }

        /// <summary>
        /// list全排列
        /// </summary>
        /// <param name="list">需要排列的List</param>
        /// <param name="k">开始位置</param>
        /// <param name="m">结束位置</param>
        protected void Perm(List<int> list, int k, int m)
        {
            if (k == m)
            {
                for (int i = 0; i <= m; i++)
                {
                    Response.Write(list[i].ToString() + " ");
                }
                Response.Write("<br>");
            }
            else
            {
                for (int i = k; i <= m; i++)
                {
                    Swap(ref list,k,i);
                    Perm(list, k + 1, m);
                    Swap(ref list, k, i);
                }
            }
        }

        private void Swap(ref List<int> list,int a,int b)
        {
            int temp = list[a];
            list[a] = list[b];
            list[b] = temp;
        }


 

你可能感兴趣的:(算法,String,list,object,Class,button)