generating permunation——全排列(算法汇总)

#include <iostream>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <iterator>
#include <algorithm>
using namespace std; #define MAX 10
int used[MAX]; //用来标记数字是否已经在前面使用过
int result[MAX]; //存放结果
int array[MAX] = {1,2,3,4,5,6,7,8,9,10}; void swap(int x, int y){ int temp = array[x];
array[x]=array[y];
array[y]=temp; return;
} template<typename T>
void printArray(T array[], int size){
int i; for (i=0;i<size;i++)
cout << array[i] << " ";
cout << endl; return;
} /*递归(非字典序)*/
template<typename T>
void recur_permute(T array[], int begin, int end)
{
int i;
if (begin==end)
{
printArray(array, end+1);
return;
}
else{
//for循环遍历该排列中第一个位置的所有可能情况
for (i=begin; i<=end; i++){
swap(begin, i); //循环变换第一个位置
recur_permute(array, begin+1, end); //DFS
swap(begin, i); //回溯,保持原排列
}
}
} /*递归(字典序)*/
template<typename T>
void lexi_recur_permute(T array[], int begin, int end)
{
int i;
if (begin == end+1)
{
printArray(result, end+1);
return;
}
else{
for (i=0; i<=end; i++){
if(!used[i]) //没有标记
{
used[i]=1; //标记
result[begin]=array[i]; //记录结果
lexi_recur_permute(array, begin+1, end);
used[i]=0; //回溯
} }
}
} /*STL(字典序)*/
template<typename T>
void stl_permute(T array[], int size)
{
vector<T>::iterator begin, end;
vector<T> Pattern(size) ;
ostream_iterator<T> out_it(cout, " ") ; //int size=sizeof(array)/sizeof(T); for(int i=0; i<size; i++)
Pattern[i]=array[i]; begin = Pattern.begin() ;
end = Pattern.end() ; do
{
copy(begin, end, out_it) ;
cout << endl ;
}while ( next_permutation(begin, end) );
} int get_factorial(int n)
{
if(1==n || 0==n) return 1;
else return n*get_factorial(n-1);
} /*给定元素个数n,以及数组p,返回全排列的序号*/
template<typename T>
int perm2num(int n, T *p){
int i, j, num=0,k=1;
for (i=n-2;i>=0;i--)//注意下标从0开始
{
for (j=i+1;j<n;j++)
if (p[j]<p[i]) num+=k;//是否有逆序,如有,统计
k*=n-i; //每一轮后k=(n-i)!,
}
return num;
} /*BFS(字典序)*/
template<typename T>
void bfs_permute(T array[], int size)
{
int idx=0;
int cnt=get_factorial(size); list<T> ls;
queue<list<T>> q; ls.push_back(array[0]); q.push(ls);
while(!q.empty())
{
list<T> cur_perm = q.front();
if(cur_perm.size() == size) //第n层的第一个元素长度等于size,循环结束
break;
if(cur_perm.size() != idx) //不相等
idx++; q.pop(); list<T>::iterator it = cur_perm.end();
while( it!=cur_perm.begin() )
{
cur_perm.insert(it, array[idx]); //插入
q.push(cur_perm);
it=cur_perm.erase(--it); //还原 --it; //向前一步找插入点 if( it==cur_perm.begin() ) //第一个插入点特殊处理并结束
{
cur_perm.push_front(array[idx]);
q.push(cur_perm);
cur_perm.clear();
break;
}
}
}
print_queue(q, size, cnt);
} template<typename T>
void print_queue(queue<list<T>> q, int size, int cnt)
{
vector<list<T>> vec(cnt);
T* perm=new T[size]; //存储当前排列 /*映射*/
while(!q.empty())
{
list<T> cur_perm=q.front();
q.pop();
list<T>::iterator it=cur_perm.begin(); int idx=0,i=0;
int n=size;
while(it!=cur_perm.end())
{
perm[i++]=*it++;
} //当前排列放入全排列对应位置
idx=perm2num(size, perm);
vec[idx]=cur_perm;
}
delete []perm; /*输出*/
vector<list<T>>::iterator vit=vec.begin();
for(;vit!=vec.end();vit++)
{
list<T> cur_perm=*vit;
list<T>::iterator lit=cur_perm.begin();
for(;lit!=cur_perm.end();lit++)
{
cout<<*lit<<" ";
}
cout<<endl;
}
} int main(){
recur_permute(array, 0, 3);
lexi_recur_permute(array, 0,3);
stl_permute(array, 4);
bfs_permute(array, 4);
return 0;
}

上面一共提供了4种全排列的方法,包括递归非字典序版本、递归字典序版本、标准库版本和BFS字典序版本,当然BFS非字典序实现相对于BFS字典序版本更加简洁,稍加修改即可。

说明:递归版本基于网上现有代码修改而成,标准库版本参照msdn sample修改而成,最后的BFS版本是由本人在看到题目后思考而来,并实现之(递归版本很久之前写过),所有四种算法都加了模板。当然BFS版本效率相对于递归要快,相对于STL版本则较慢,仅仅提供一种思路而已

最后再附上STL版本算法思路及修改后的代码(仅仅为了可读性):

思路

给定已知序列P =  A1A2A3.....An
对P按字典排序,得到P的一个最小排列Pmin = A1A2A3....An ,满足Ai > A(i-1) (1 < i <= n)
从Pmin开始,找到刚好比Pmin大的一个排列P(min+1),再找到刚好比P(min+1)大的一个排列,如此重复。
1.从后向前(即从An->A1),找到第一对为升序的相邻元素,即Ai < A(i+1)。
  若找不到这样的Ai,说明已经找到最后一个全排列,可以返回了。
2.从后向前,找到第一个比Ai大的数Aj,交换Ai和Aj。
3.将排列中A(i+1)A(i+2)....An这个序列的数逆序倒置,即An.....A(i+2)A(i+1)。因为由前面第1、2可以得知,A(i+1)>=A(i+2)>=.....>=An,这为一个升序序列,应将该序列逆序倒置,所得到的新排列才刚刚好比上个排列大。
4.重复步骤1-3,直到返回。
这个算法是C++ STL算法next_permutation的思想。
 
代码

generating permunation的更多相关文章

  1. generating permunation——全排列(算法汇总)

    本文一共提供了4种全排列的方法,包括递归非字典序版本.递归字典序版本.标准库版本和BFS字典序版本,当然BFS非字典序实现相对于BFS字典序版本更加简洁,稍加修改即可. 说明:递归版本基于网上现有代码 ...

  2. Codeforces 722D. Generating Sets

    D. Generating Sets time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

  3. Xcode8 pod install 报错 “Generating Pods project Abort trap

    Xcode8 pod install 报错 "Generating Pods project Abort trap 今天在写一个新项目的时候,使用cocoapods在执行 $ pod ins ...

  4. CF722D. Generating Sets[贪心 STL]

    D. Generating Sets time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

  5. The resource identified by this request is only capable of generating responses with characteristics

    [转]今天在调试springMVC的时候,在将一个对象返回为json串的时候,浏览器中出现异常: The resource identified by this request is only cap ...

  6. Auto generating Entity classes with xsd.exe for XML Serialization and De-Serialization

    More info here: http://blogs.msdn.com/b/yojoshi/archive/2011/05/14/xml-serialization-and-deserializa ...

  7. ORA-1461 encountered when generating server alert SMG-3500

    Doc ID 461911.1 Patch 6602742 Applies to: Oracle Database - Enterprise Edition - Version 10.2.0.3 an ...

  8. 读书笔记 1 of Statistics :Moments and Moment Generating Functions (c.f. Statistical Inference by George Casella and Roger L. Berger)

    Part 1: Moments Definition 1 For each integer $n$, the nth moment of $X$, $\mu_n^{'}$ is \[\mu_{n}^{ ...

  9. Which Clang Warning Is Generating This Message?

    Which Clang Warning Is Generating This Message? 根据前面页面制作的pdf:clangwarninglist.pdf 百度网盘:http://pan.ba ...

随机推荐

  1. IOS的UITextField,UIButton,UIWebView它描述的一些属性和IOS提示图像资源

    有时UI要开发的资源与实际frame不符.这一次,我们要绘制图片 UIImage* image = [[UIImage imageNamed:@"text_field_bg.png" ...

  2. C语言星号的秘密

    C语言星号的秘密 星号的秘密 1.乘法运算符   2.定义指针 int *p = 0; 还是 int* p = 0;? 后一种比较容易这样理解:定义了一个变量p,它是指针型的(更详细一点,是指向int ...

  3. POJ 3299 Humidex(简单的问题)

    [简要题意]:什么是温度,湿度--,之间的转换.. [分析]:式已被赋予. // 252k 0Ms /* 当中exp表示的是求e的x次幂 解法就直接依据题目中的公式解决就好!! */ #include ...

  4. 请确保在编译时已将“AjaxControlToolkit.Properties.Resources.NET4.resources”正确嵌入或链接到程序集“AjaxControlToolkit”

    原文:请确保在编译时已将"AjaxControlToolkit.Properties.Resources.NET4.resources"正确嵌入或链接到程序集"AjaxC ...

  5. C#中调用Outlook API 发起会议

    原文:C#中调用Outlook API 发起会议 在我上一篇博文中曾提到了 SharePoint 中调用传出电子邮件中的邮件服务器及地址发送邮件 但是,里面的方法只能用于发送普通电子邮件.如果要发起会 ...

  6. [译]Java 设计模式之备忘录

    (文章翻译来自Java Design Pattern: Memento) memento是一个保存另外一个对象内部状态拷贝的对象.这样以后就可以将该对象恢复到原先保存的状态. 在将来时空旅行将成为显示 ...

  7. ReviewBoard安装和配置说明

    眼下部门还没有採用Pair Programming那种时时刻刻都在review代码的工作方式,代码Review多採用走查方式.即代码写完后召开一个Code Review的Meeting,集中时间和经验 ...

  8. 我的Android 4 学习系列之使用 Internet 资源

    目录 连接Internet资源 分析XML资源 使用Download Manager下载文件 查询Download manager 使用Account Manager 对 Google App Eng ...

  9. svn外网访登录不进去提示证书错误Authorization Required

    为了外网能访问内网svn.于是坐在外网端口映射.但是奇怪的是内网能访问,外网总也登录不进去.以为是浏览器版本低 但是其他浏览器也一样.最后客户端也登录不进去.提示报错:  Authorization  ...

  10. Product Trader(操盘手)

    Product Trader(操盘手) 索引 意图 结构 参与者 适用性 效果 相关模式 实现 实现方式(一):Product Trader 的示例实现. 意图 使客户程序可以通过命名抽象超类和给定规 ...