生成所有错位排列的算法

Posted wskit

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了生成所有错位排列的算法相关的知识,希望对你有一定的参考价值。

所谓N元错位排列,就是指对应于1,2,--,N的N元排列Im(m=1,2,---,N),满足Im!=m,算法的目的是构造出所有这样的错位排列,依据的基本思想是回溯法,在沿栈向下试探的过程中逐步扩大部分错位排列的规模,当发现无法找到下一个部分错位排列的元素时就向上回溯,继续试探,当栈空间首元素stack[0]==N+1时,表明首元素为2,--,N的所有错位排列已全部试探得到,错位排列生成完毕,退出循环。这里给出算法,该算法生成对应于1,2,---,N的所有N元错位排列

代码(C++)

 

  1 #include "stdafx.h"
  2 #include <vector>
  3 #include <iostream>
  4 using namespace std;
  5 
  6 #define N 5   //问题规模,生成对应于1,2,---,N的所有N元错位排列
  7 
  8 int Search(const vector<bool> &occupy, int i ,int j)
  9 {
 10     for (; i < occupy.size(); ++i)
 11     {
 12         if (i + 1 != j && occupy[i] == false)
 13         {
 14             return i + 1;
 15         }
 16     }
 17     return 0;
 18 }
 19 
 20 int main()
 21 {
 22     vector<int> a(N, 0);
 23     vector<bool> occupy(N, false);  //对于栈中已生成的错位排列中的任意值i,occupy[i-1]==true,对于1,2---,N中不在错位排列栈中的任意元素i,occupy[i-1]=false
 24     bool TF = true;  //循环过程中回溯至本层为false,前进至本层为true
 25     int i = 0;  //存放错位排列的栈的栈顶指针
 26     int count = 0;  //统计错位排列数
 27     while (true)
 28     {
 29         if (i == 0)
 30         {
 31             if (TF == true)
 32             {
 33                 a[i] = 2;
 34                 occupy[a[i] - 1] = true;
 35                 ++i;
 36             }
 37             else
 38             {
 39                 occupy[a[i] - 1] = false;
 40                 ++a[i];
 41                 if (a[i] > N)
 42                     break;
 43                 occupy[a[i] - 1] = true;
 44                 ++i;
 45                 TF = true;
 46             }
 47         }
 48         else
 49         {
 50             int temp;
 51             if (TF == true)
 52             {
 53                 if ((temp = Search(occupy, 0, i + 1)) == 0)
 54                 {
 55                     --i;
 56                     TF = false;
 57                     continue;
 58                 }
 59                 else
 60                 {
 61                     a[i] = temp;
 62                     occupy[temp-1] = true;
 63                 }
 64             }
 65             else
 66             {
 67                 if ((temp = Search(occupy, a[i], i + 1)) == 0)
 68                 {
 69                     occupy[a[i] - 1] = false;
 70                     --i;
 71                     continue;
 72                 }
 73                 else
 74                 {
 75                     occupy[a[i] - 1] = false;
 76                     a[i] = temp;
 77                     occupy[temp - 1] = true;
 78                 }
 79             }
 80 
 81             if (i != a.size() - 1)
 82             {
 83                 ++i;
 84                 TF = true;
 85             }
 86             else
 87             {
 88                 ++count;
 89                 cout << ""<<count<<"个错位排列:" << endl;
 90                 for (const int &m : a)
 91                 {
 92                     cout << m << " ";
 93                 }
 94                 cout << endl;
 95                 for (int j = 1; j <= N; ++j)
 96                 {
 97                     cout << j << " ";
 98                 }
 99                 cout << endl;
100                 cout << endl;
101                 TF = false;
102             }
103 
104         }
105     }
106     return 0;
107 }

 

运行结果(N=5时)

技术分享图片

以上是关于生成所有错位排列的算法的主要内容,如果未能解决你的问题,请参考以下文章

堆算法的问题:并非所有排列都生成

是否有任何排列算法?

错位排列及有关例题

是否有一种算法可以生成多重集的所有唯一循环排列?

C语言数字全排列的问题(急!!)求C代码和算法

请解释此算法以获取字符串的所有排列