STL---next_permutation 实现

本文深入探讨了STL中的next_permutation和prev_permutation算法,解析了它们的工作原理及应用,通过实例展示了如何使用这两个函数来生成序列的所有可能排列。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

STL中提供了两个关于计算排列组合关系的算法,分别是next_permutation 和 prev_permutation

 

next_permutation :

分析:给出一个排列P,求出下一个排列P1是什么?

 

比如 P = 1 2 3 4 5。显然P1: 1 2 3 5 4。 P2:1 2 4 3 5。

 

规律: P->P1   :直接对 4 5 逆序。

       P1->P2  : 后两个元素已经是逆序了,接下来就从后往前找出第一个正序的两个元素,也就是3 5,然后把3 和 4(逆序找第一个比3大的元素)交换,再把5(包括)之后的元素逆序。就可以得到下一个排列了。.

核心:逆序不可能存在下一个排列了,已经是最大了, 所以我们要先找到第一个递增序列(i < ii),然后逆序找出第一个比i大的元素x(保证x 是比i大中的 最小),然后swap(x,i), 然后翻转ii之后的。

prev_permutation和next_permutation是相反操作。

 

next_permutation:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<string>
#include<vector>
#include<queue>
#include<stack>
#include<cmath>
#include<set>
#include<map>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define oo cout<<"!!!"<<endl;
typedef long long ll;
typedef unsigned long long ull;
#define ms(s) memset(s, 0, sizeof(s))
const int inf = 0x3f3f3f3f;
//head

const int maxn = 1e6+11;


template < typename T>
bool Next_permutation(T first,T last){
	if(first == last)return false;//空区间
	T i = first;
	i++;
	if(i == last)return false;//1个元素
	i = last;
	i--;

	while(1){
		T ii = i;
		i--;//逆序找出第一个 *i<*ii;

		if(*i < *ii){
			T j = last;
			while(!(*i < *--j));//倒序找到第一个比*i大的元素
			iter_swap(i,j);//交换*i,*j
			reverse(ii,last);//ii之后的全部逆序
			return true;
		}
		if(i == first){//进行到最前面了,全部逆序返回false
			reverse(first,last);
			return false;
		}
	}
}
int main() 
{	
	std::vector<int> v;
	rep(i,1,4)v.push_back(i);
	do{
		for(auto x:v)cout << x << " ";
		cout << endl;
	}while(Next_permutation(v.begin(),v.end()) );

    return 0;
}

 

prev_permutation:

template < typename T>
bool Prev_permutation(T first,T last){
    if(first == last)return false;//空区间
    T i = first;
    i++;
    if(i == last)return false;//1个元素
    i = last;
    i--;
 
    while(1){
        T ii = i;
        i--;//逆序找出第一个 *i>*ii(递减);
 
        if(*i > *ii){

            T j = last;
            while(!(*i > *--j));//倒序找到第一个比*i小的元素
            iter_swap(i,j);//交换*i,*j
            reverse(ii,last);//ii之后的全部逆序
            return true;
        }
        if(i == first){//进行到最前面了,全部逆序返回false
            reverse(first,last);
            return false;
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值