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. javascript中数组常用方法总结

    原文:javascript中数组常用方法总结 在javascript的基础编程中,数组是我们最常遇到的,那么数组的一些常用方法也是我们必须要掌握的,下面我们总结一下数组中常用的方法. toString ...

  2. javascript系列之核心知识点(一)

    JavaScript. The core. 1.对象 2.原型链 3.构造函数 4.执行上下文堆栈 5.执行上下文 6.变量对象 7.活动对象 8.作用域链 9.闭包 10.this值 11.总结 这 ...

  3. OWIN– 解耦,协作和开放

    OWIN的理解和实践(一) – 解耦,协作和开放 概述 OWIN的全称是Open Web Interface For .Net, 是MS在VS2013期间引入的全新的概念, 网上已经有不少的关于它的信 ...

  4. C语言学习之路,第一篇章。

    看的书是 C  primer plus  ,这本书好评很多, 学过C#,没有精通,了解Java,所以看这本书会很容易上手,编译器用的是VC++6.0,因为VS2010好像不支持C99标准,有些代码功能 ...

  5. 用HMM(隐马)图解三国杀的于吉“质疑”

    ·背景 最近乘闲暇之余初探了HMM(隐马尔科夫模型),觉得还有点意思,但是网上的教程都超级枯草,可读性很差,抄来抄去的,一堆公式仍在你面前,谁能搞的懂(但园内的两篇写的还算不错.真才实学).在熬制3天 ...

  6. Windows Phone 8.1 多媒体(2):视频

    原文:Windows Phone 8.1 多媒体(2):视频 Windows Phone 8.1 多媒体(1):相片 Windows Phone 8.1 多媒体(2):视频 Windows Phone ...

  7. Pointers to classes (From the note of my firend)

     Pointers to classes Objects can also be pointed to by pointers: Once declared, a class becomes a ...

  8. 3-05. 寻求倒数第二链线性表K项目(15)(STL list应用 ZJU_PAT)

    主题链接:http://pat.zju.edu.cn/contests/ds/3-05 给定一系列正整数,请设计一个尽可能高效的算法.查找倒数第K个位置上的数字. 输入格式说明: 输入首先给出一个正整 ...

  9. 原生AJAX基础讲解及兼容处理

    原文:原生AJAX基础讲解及兼容处理 AJAX = Asynchronous JavaScript and XML (异步的JavaScript和XML). AJAX不是新技术 ,但却是热门的技术.它 ...

  10. Appium0.18.x迁移到Appium1.x须知事项

    英文原版:https://github.com/appium/appium/blob/master/docs/en/advanced-concepts/migrating-to-1-0.md Migr ...