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. JS function立即调用的几种写法

    //立即执行 (function () { alert(1) })() //立即执行 !function () { alert(1) }() //立即执行 +function () { alert(1 ...

  2. C#中利用双缓冲技术解决绘图闪屏问题。

    这段时间在做一个小型游戏,在界面显示的时候用到了一些图形.一开始涉及到的图形全都用控件的背景图片代替了.这样游戏运行的时候存在的一个很大的问题是游戏运行很慢.小组成员费尽周折,即将放弃,每一个成员都愁 ...

  3. Metrics监控应用

    使用Metrics监控应用程序的性能   在编写应用程序的时候,通常会记录日志以便事后分析,在很多情况下是产生了问题之后,再去查看日志,是一种事后的静态分析.在很多时候,我们可能需要了解整个系统在当前 ...

  4. [LeetCode]N-Queens 八皇后问题扩展(经典深层搜索)

    The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens ...

  5. SSAS系列——【07】多维数据(查询Cube)

    原文:SSAS系列——[07]多维数据(查询Cube) 1.什么是MDX? MDX叫做"多维表达式",是一种查询语言,是一种和SQL类似的查询语言,它基于 XML for Anal ...

  6. linux open

    一直记住不打开文件时候的mode,今天发现原来可以直接用0644这样的八进制数字代替,好开森 #include <stdio.h> #include <sys/types.h> ...

  7. 批处理命令篇--配置免安装mysql 5.6.22, 以及1067错误的一个解决方法

    mysql 服务启动出现1067错误的一个解决方法: 当服务启动出现1067错误时,可查看“windows 事件查看器”,发现类似错误提示 Can't find messagefile 'F:\    ...

  8. 新秀nginx源代码分析数据结构篇(两) 双链表ngx_queue_t

    nginx源代码分析数据结构篇(两) 双链表ngx_queue_t Author:Echo Chen(陈斌) Email:chenb19870707@gmail.com Blog:Blog.csdn. ...

  9. CSS3制作日历

    目标是制作如下面DEMO显示的一个日历效果: HTML Markup 先来看看其结构: <div class="calendar"> <span class=&q ...

  10. orcale复制表结构及其数据

    http://hi.baidu.com/tag/Oracle/feeds http://hi.baidu.com/gqftuisidibabiq/item/14d306cc87cbdf45bcef69 ...