全排列算法递归与非递归解析+代码
2017-08-22 10:39
190 查看
(一)递归的全排列算法
(A、B、C、D)的全排列为
1、A后面跟(B、C、D)的全排列
2、B后面跟(A、C、D)的全排列
3、C后面跟(A、B、D)的全排列
4、D后面跟(A、B、C)的全排列
而对1中的(B、C、D)照样可以按照上面的形式进行分解。
[cpp]
view plain
copy
print?
/**********************************************************************
* Compiler: GCC
* Last Update: Mon 07 May 2012 07:08:58 PM CST
* File Name: 1.cpp
* Description: 利用stl中的next_permutation进行全排列
************************************************************************/
#include <iostream>
using namespace std;
template<typename T>
void permutation(T array[], int begin, int end)
{
int i;
if(begin ==
4000
end){
for(i = 0; i <= end; ++i){
cout<<array[i]<<" ";
}
cout<<endl;
return;
} else {
//for循环遍历该排列中第一个位置的所有可能情况
for(i = begin; i <= end; ++i) {
swap(array[i], array[begin]);
permutation(array, begin + 1, end);
swap(array[i], array[begin]);
}
}
}
int main(int argc, char **argv)
{
int a[4] = {1, 2, 3, 4};
permutation(a, 0, sizeof(a) / sizeof(int) - 1);
return 0;
}
(二)非递归全排列算法,即按字典序排列算法。
基本思想是:
1.对初始队列进行排序,找到所有排列中最小的一个排列Pmin。
2.找到刚刚好比Pmin大比其它都小的排列P(min+1)。
3.循环执行第二步,直到找到一个最大的排列,算法结束。
如排列ABCDE,这是所有排列中最小的一个排列,刚好比ABCDE大的排列是:ABCED。
算法如下:
给定已知序列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的思想。
[cpp]
view plain
copy
print?
/**********************************************************************
* Compiler: GCC
* Last Update: Mon 07 May 2012 07:08:58 PM CST
* File Name: 1.cpp
* Description:
************************************************************************/
#include <iostream>
#include <cstring>
using namespace std;
//交换数组a中下标为i和j的两个元素的值
void swap(int *a,int i,int j)
{
a[i]^=a[j];
a[j]^=a[i];
a[i]^=a[j];
}
//将数组a中的下标i到下标j之间的所有元素逆序倒置
void reverse(int a[],int i,int j)
{
for(; i<j; ++i,--j) {
swap(a,i,j);
}
}
void print(int a[],int length)
{
for(int i=0; i<length; ++i)
cout<<a[i]<<" ";
cout<<endl;
}
//求取全排列,打印结果
void combination(int a[],int length)
{
if(length<2) return;
bool end=false;
while(true) {
print(a,length);
int i,j;
//找到不符合趋势的元素的下标i
for(i=length-2; i>=0; --i) {
if(a[i]<a[i+1]) break;
else if(i==0) return;
}
for(j=length-1; j>i; --j) {
if(a[j]>a[i]) break;
}
swap(a,i,j);
reverse(a,i+1,length-1);
}
}
int main(int argc, char **argv)
{
int a[4] = {1, 2, 3, 4};
combination(a, sizeof(a) / sizeof(int));
return 0;
}
用STL实现:
STL有一个函数next_permutation(),它的作用是如果对于一个序列,存在按照字典排序后这个排列的下一个排列,那么就返回true且产生这个排列,否则返回false。
[cpp]
view plain
copy
print?
/**********************************************************************
* Compiler: GCC
* Last Update: Mon 07 May 2012 07:08:58 PM CST
* File Name: 1.cpp
* Description: 利用stl中的next_permutation进行全排列
************************************************************************/
#include <iostream>
#include <algorithm>
using namespace std;
template <typename BidirectionalIterator>
void permutation(BidirectionalIterator array, int len)
{
sort(array, array + len);
do{
for(int i = 0; i < len; ++i){
cout<<array[i]<<" ";
}
cout<<endl;
}while(next_permutation(array, array + len));
}
int main(int argc, char **argv)
{
int a[4] = {1, 2, 3, 4};
permutation(a, sizeof(a) / sizeof(int));
return 0;
}
@@@@@@@@
来源:http://blog.csdn.net/hackbuteer1/article/details/6657435
http://plutoblog.iteye.com/blog/976216
http://blog.csdn.net/aipb2008/article/details/2227490
(A、B、C、D)的全排列为
1、A后面跟(B、C、D)的全排列
2、B后面跟(A、C、D)的全排列
3、C后面跟(A、B、D)的全排列
4、D后面跟(A、B、C)的全排列
而对1中的(B、C、D)照样可以按照上面的形式进行分解。
[cpp]
view plain
copy
print?
/**********************************************************************
* Compiler: GCC
* Last Update: Mon 07 May 2012 07:08:58 PM CST
* File Name: 1.cpp
* Description: 利用stl中的next_permutation进行全排列
************************************************************************/
#include <iostream>
using namespace std;
template<typename T>
void permutation(T array[], int begin, int end)
{
int i;
if(begin ==
4000
end){
for(i = 0; i <= end; ++i){
cout<<array[i]<<" ";
}
cout<<endl;
return;
} else {
//for循环遍历该排列中第一个位置的所有可能情况
for(i = begin; i <= end; ++i) {
swap(array[i], array[begin]);
permutation(array, begin + 1, end);
swap(array[i], array[begin]);
}
}
}
int main(int argc, char **argv)
{
int a[4] = {1, 2, 3, 4};
permutation(a, 0, sizeof(a) / sizeof(int) - 1);
return 0;
}
/********************************************************************** * Compiler: GCC * Last Update: Mon 07 May 2012 07:08:58 PM CST * File Name: 1.cpp * Description: 利用stl中的next_permutation进行全排列 ************************************************************************/ #include <iostream> using namespace std; template<typename T> void permutation(T array[], int begin, int end) { int i; if(begin == end){ for(i = 0; i <= end; ++i){ cout<<array[i]<<" "; } cout<<endl; return; } else { //for循环遍历该排列中第一个位置的所有可能情况 for(i = begin; i <= end; ++i) { swap(array[i], array[begin]); permutation(array, begin + 1, end); swap(array[i], array[begin]); } } } int main(int argc, char **argv) { int a[4] = {1, 2, 3, 4}; permutation(a, 0, sizeof(a) / sizeof(int) - 1); return 0; }
(二)非递归全排列算法,即按字典序排列算法。
基本思想是:
1.对初始队列进行排序,找到所有排列中最小的一个排列Pmin。
2.找到刚刚好比Pmin大比其它都小的排列P(min+1)。
3.循环执行第二步,直到找到一个最大的排列,算法结束。
如排列ABCDE,这是所有排列中最小的一个排列,刚好比ABCDE大的排列是:ABCED。
算法如下:
给定已知序列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的思想。
[cpp]
view plain
copy
print?
/**********************************************************************
* Compiler: GCC
* Last Update: Mon 07 May 2012 07:08:58 PM CST
* File Name: 1.cpp
* Description:
************************************************************************/
#include <iostream>
#include <cstring>
using namespace std;
//交换数组a中下标为i和j的两个元素的值
void swap(int *a,int i,int j)
{
a[i]^=a[j];
a[j]^=a[i];
a[i]^=a[j];
}
//将数组a中的下标i到下标j之间的所有元素逆序倒置
void reverse(int a[],int i,int j)
{
for(; i<j; ++i,--j) {
swap(a,i,j);
}
}
void print(int a[],int length)
{
for(int i=0; i<length; ++i)
cout<<a[i]<<" ";
cout<<endl;
}
//求取全排列,打印结果
void combination(int a[],int length)
{
if(length<2) return;
bool end=false;
while(true) {
print(a,length);
int i,j;
//找到不符合趋势的元素的下标i
for(i=length-2; i>=0; --i) {
if(a[i]<a[i+1]) break;
else if(i==0) return;
}
for(j=length-1; j>i; --j) {
if(a[j]>a[i]) break;
}
swap(a,i,j);
reverse(a,i+1,length-1);
}
}
int main(int argc, char **argv)
{
int a[4] = {1, 2, 3, 4};
combination(a, sizeof(a) / sizeof(int));
return 0;
}
/********************************************************************** * Compiler: GCC * Last Update: Mon 07 May 2012 07:08:58 PM CST * File Name: 1.cpp * Description: ************************************************************************/ #include <iostream> #include <cstring> using namespace std; //交换数组a中下标为i和j的两个元素的值 void swap(int *a,int i,int j) { a[i]^=a[j]; a[j]^=a[i]; a[i]^=a[j]; } //将数组a中的下标i到下标j之间的所有元素逆序倒置 void reverse(int a[],int i,int j) { for(; i<j; ++i,--j) { swap(a,i,j); } } void print(int a[],int length) { for(int i=0; i<length; ++i) cout<<a[i]<<" "; cout<<endl; } //求取全排列,打印结果 void combination(int a[],int length) { if(length<2) return; bool end=false; while(true) { print(a,length); int i,j; //找到不符合趋势的元素的下标i for(i=length-2; i>=0; --i) { if(a[i]<a[i+1]) break; else if(i==0) return; } for(j=length-1; j>i; --j) { if(a[j]>a[i]) break; } swap(a,i,j); reverse(a,i+1,length-1); } } int main(int argc, char **argv) { int a[4] = {1, 2, 3, 4}; combination(a, sizeof(a) / sizeof(int)); return 0; }
用STL实现:
STL有一个函数next_permutation(),它的作用是如果对于一个序列,存在按照字典排序后这个排列的下一个排列,那么就返回true且产生这个排列,否则返回false。
[cpp]
view plain
copy
print?
/**********************************************************************
* Compiler: GCC
* Last Update: Mon 07 May 2012 07:08:58 PM CST
* File Name: 1.cpp
* Description: 利用stl中的next_permutation进行全排列
************************************************************************/
#include <iostream>
#include <algorithm>
using namespace std;
template <typename BidirectionalIterator>
void permutation(BidirectionalIterator array, int len)
{
sort(array, array + len);
do{
for(int i = 0; i < len; ++i){
cout<<array[i]<<" ";
}
cout<<endl;
}while(next_permutation(array, array + len));
}
int main(int argc, char **argv)
{
int a[4] = {1, 2, 3, 4};
permutation(a, sizeof(a) / sizeof(int));
return 0;
}
/********************************************************************** * Compiler: GCC * Last Update: Mon 07 May 2012 07:08:58 PM CST * File Name: 1.cp b811 p * Description: 利用stl中的next_permutation进行全排列 ************************************************************************/ #include <iostream> #include <algorithm> using namespace std; template <typename BidirectionalIterator> void permutation(BidirectionalIterator array, int len) { sort(array, array + len); do{ for(int i = 0; i < len; ++i){ cout<<array[i]<<" "; } cout<<endl; }while(next_permutation(array, array + len)); } int main(int argc, char **argv) { int a[4] = {1, 2, 3, 4}; permutation(a, sizeof(a) / sizeof(int)); return 0; }
@@@@@@@@
来源:http://blog.csdn.net/hackbuteer1/article/details/6657435
http://plutoblog.iteye.com/blog/976216
http://blog.csdn.net/aipb2008/article/details/2227490
相关文章推荐
- 全排列算法的递归与非递归实现
- 回溯算法 DFS深度优先搜索 (递归与非递归实现)
- 【算法】快速排序算法(递归实现 从小到大排列) 排序范围(0~n-1) n为数组元素个数
- 全排列算法非递归实现和递归实现
- 全排列问题问题的两种算法--递归与字典序
- KMP算法之我见(NEXT数组的递归解析)
- 排列组合算法的递归实现
- 结点遍历C语言实现二叉树的常用的算法(递归与非递归实现遍历)
- 全排列问题算法实现--递归
- 0002算法笔记——【递归】排列问题,整数划分问题,Hanoi问题
- 全排列算法之非递归实现
- 算法训练 求先序排列 【二叉树的递归遍历】
- hdu2586[lca离线tarjon算法][递归与非递归]
- 蓝桥杯常用算法知识点:【递归】m个A与n个B的全排列个数
- 一些常用算法[数组全排列算法,单链表反转(递归实现),字符串反转,桶排序]
- 全排列算法递归及STL实现,八皇后问题
- 全排列,去重全排列的递归与非递归实现
- C++ 递归位置排列算法及其应用
- 算法设计-全排列递归
- 先序遍历二叉树的递归实现与非递归实现深入解析