7.2.1 生成1~n的排列(全排列)【STL__next_permutation()_的应用】

#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
int a[20];
void print_permutation(int n, int a[], int cur){
    int i, j;
    if(cur == n){
        for(i = 0; i < n; ++i)  printf("%d ",a[i]);
        printf("\n");
    }
    else for(i = 1; i <= n; ++i){
        bool flag = true;
        for(j = 0; j < cur; ++j)    if(a[j] == i)   flag = false;
        if(flag){
            a[cur] = i;
            print_permutation(n, a, cur+1);
        }
    }
}
int main(){
    print_permutation(3, a, 0);
    return 0;
}

使用STL的next_permutation()会更加方便:

next_permutation实现原理

在《STL源码解析》中找到了这个函数,在此也简单叙述一下原理:

在STL中,除了next_permutation外,还有一个函数prev_permutation,两者都是用来计算排列组合的函数。前者是求出下一个排列组合,而后者是求出上一个排列组合。所谓“下一个”和“上一个”,书中举了一个简单的例子:对序列 {a, b, c},每一个元素都比后面的小,按照字典序列,固定a之后,a比bc都小,c比b大,它的下一个序列即为{a, c, b},而{a, c, b}的上一个序列即为{a, b, c},同理可以推出所有的六个序列为:{a, b, c}、{a, c, b}、{b, a, c}、{b, c, a}、{c, a, b}、{c, b, a},其中{a, b, c}没有上一个元素,{c, b, a}没有下一个元素。

next_permutation的函数原型如下:

template<class BidirectionalIterator>
bool next_permutation(
      BidirectionalIterator _First,
      BidirectionalIterator _Last
);
template<class BidirectionalIterator, class BinaryPredicate>
bool next_permutation(
      BidirectionalIterator _First,
      BidirectionalIterator _Last,
      BinaryPredicate _Comp
 );

对于第二个重载函数的第三个参数,默认比较顺序为小于。如果找到下一个序列,则返回真,否则返回假。

所以,这道题目的代码可以这么写:

 1 #include <iostream>
 2 #include <algorithm>
 3 using namespace std;
 4 int main(){
 5     int n,A[100],cur=0;
 6     cin >> n;
 7     int i;
 8     for(i=0; i<n; ++i)  A[i]=i+1;
 9     do{
10         for(i=0; i<n; i++)  cout<<A[i]<<‘ ‘;
11         cout<<endl;
12     }
13     while(next_permutation(A,A+n));
14     return 0;
15 }

小结

用next_permutation和prev_permutation求排列组合很方便,但是要记得包含头文件#include <algorithm>。

虽然最后一个排列没有下一个排列,用next_permutation会返回false,但是使用了这个方法后,序列会变成字典序列的第一个,如cba变成abc。prev_permutation同理。

7.2.1 生成1~n的排列(全排列)【STL__next_permutation()_的应用】,布布扣,bubuko.com

时间: 2024-10-09 14:19:07

7.2.1 生成1~n的排列(全排列)【STL__next_permutation()_的应用】的相关文章

算法竞赛入门经典_第七章 暴力求解法_7.2枚举排列:生成1~n的排列

版权所有,欢迎转载,转载请注明出处,谢谢 生成1~n的排列 递归思想:先输出所有以1开头的排列(这一步是递归调用),然后输出以2开头的排列(这一步是递归调用),接着是以3开头的排列······最后才是以n开头的排列. //vs2012测试代码 #include<iostream> using namespace std; void print_permutation(int n, int* A, int cur) { if(cur==n)//递归边界 { for(int i=0; i<n

枚举排列 之 “生成1~n的排列”

一.原题 输入n之后,生成1~n的排列. (题目来源:<算法竞赛入门经典>[刘汝佳]) 二.题目源代码 #include <stdio.h> #define MAXN 1000 int a[MAXN][MAXN]; void print_permutation(int n,int*a,int cur) { int i,j; if(cur==n) //递归边界 { for(i=0;i<n;i++) printf("%d",a[i]); printf(&quo

LeetCode 笔记21 生成第k个排列

题目是这样的: The set [1,2,3,…,n] contains a total of n! unique permutations. By listing and labeling all of the permutations in order,We get the following sequence (ie, for n = 3): "123" "132" "213" "231" "312"

生成1~~n的排列 &amp;&amp; 子集

int print_permutation(int n,int *A,int cur) { if(cur==n) { for(int i=0;i<n;i++) printf("%d",A[i]); printf("\n"); } else { for(int i=1;i<=n;i++) //填各种数 { int ok = 1; for(int j= 0; j<cur; j++) //判断是否重复出现 if( A[j]==i ) ok=0; // 1

生成n个元素的全排列 C实现

近期在准备复习算法设计的考试,下边记录一些,看笔记时突然想到的解法. 问题是这种 用递归实现 n 个元素的全排列. 当时老师给出的解答是 假定第i个元素 ri 放在首位,于是 f(r1,r2,-,rn) = f(ri U {r1, r2,-.,rn}) = U (ri & f(r1,r2, -, rn)), 当时应该是听懂了,只是如今看到这个笔记.又醉了. (这货竟然是我上课记的笔记 .... . .. .) 后来自己细致想想,事实上非常简单的 一个问题, 利用回溯法,把问题看成是一个排列树.能

挑战题之排列生成

挑战题之排列生成 Time Limit:   2000MS       Memory Limit:   65535KB Submissions:   435       Accepted:   170 Description 一自然数N,设N为3,则关于N的字典序排列为123,132,213,231,312,321.对于一个自然数N(1<= N <= 9 ) , 你要做的便是生成它的字典序排列. Input 第一行为自然数N. Output 输出对应于N的字典序排列,每个排列占一行. Samp

子集生成问题

给你一个可比较大小顺序的集合,让你生成所有按照字典序排列的子集,本文借鉴自刘汝佳算法入门经典. 方法一: 增量构造法:一次选取一个元素到集合中. #include <iostream> using namespace std; int a[20]; /*递归输出n以内所有的子集,其中cur为当前下标,初始值0*/ void print_subset(int n,int* a,int cur){ for (int i=0;i<cur;i++)//每次递归输出当前子集,靠它来最后输出上一层指

枚举排列模板、

1 //生成1~n的排列,按字典序由小到大排列 2 void print_permutation(int n,int* A,int cur) 3 { 4 if(cur==n){ //递归边界 5 for(int i=0;i<n;++i) printf("%d",A[i]); 6 printf("\n"); 7 } 8 else 9 for(int i=1;i<=n;++i){ //尝试在A[cur]中填各种数字i 10 int ok=1; 11 for(

Steinhaus-Johnson-Trotter 生成全排列算法

Steinhaus-Johnson-Trotter算法是一种基于最小变换的全排列生成算法,对于排列a[1...n],该算法通过将a[i],与a[i-1](或a[i+1])进行交换,生成下一个排列,直到所有排列生成完毕为止,这样,当前排列与其后继排列只是两个相邻位置的元素发生了调换.当然,为了防止重复生成某一个排列,算法并非随意调换某两个元素之间的位置,其生成全排列的具体规则如下. 首先,以字典序最小的排列起始,并且为该排列的每个元素赋予一个移动方向,初始所有元素的移动方向都向左. 在排列中查找这