next_permutation算法的应用和实现

STL的<algorithm>算法库里面有好多可以省事的函数,如sort,steady_sort,swap之类的函数,next_permutation也是其中之一

一般来说我们是用这货给数组求全排列,可惜这货bug(其实也不算= =)略多,不可以有相同元素,要先排好序,要定义好比较(最好要给出绝对顺序,no偏序,也不是不行,但是会造成排列数量减少)。

例如

#include <iostream>
#include <algorithm>

int main()
{
	int a[] = {1, 4, 1, 2};
	int count = 0;
	do
	{
		for(int i = 0; i < 4; i ++)
		{
			std::cout << a[i] << " ";
		}
		std::cout << std::endl;
		count ++;
	}while(std::next_permutation(a, a + 4));
	std::cout << count << std::endl;
}

上述代码的输出只是
1 4 1 2 
1 4 2 1 
2 1 1 4 
2 1 4 1 
2 4 1 1 
4 1 1 2 
4 1 2 1 
4 2 1 1 
8
而其实next_permutation的实现还是比较容易的,利用的是推导的思想,即下一个排列是比当前排列大的集合中的最小排列(有点拗口。。)

具体思想是从后往前走,当出现下坡现象(如12346543在46处会出现下坡)时,可以确定4将会是被取代的值,原因在于4之后的部分是可以被确定的最大值(因为是倒序),这时应该从4之后找出比4大的最小数(即5),此时12346543会变成12356443,将5之后的所有元素按小值排序,变成12353446,此时就得到12346543的下一个排列12353446

具体代码如下

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstdlib>

bool next_Permutation(int *arr, int size)
{
    if(arr == NULL)
    {
        return false;
    }
    int j;
    for(j = size - 2; j >= 0; j --)
    {
        if(arr[j + 1] > arr[j])
        {
            break;
        }
    }
    if(j >= 0)
    {
        int target = j + 1;
        for(int k = j + 1; k < size; k ++)
        {
            if(arr[k] > arr[j] && arr[k] < arr[target])
            {
                target = k;
            }
        }
        std::swap(arr[j], arr[target]);
        std::sort(arr + j + 1, arr + size);
        return true;
    }
    else
    {
        return false;
    }
    
}

而如果要得到全部的排列,首先要定义好元素的先序结构,进入循环前利用先序结构排好顺序,next_permutation也可以利用这个先序结构得到全部排列。

先序结构的定义不妨可以将元素本身及其下标组成结构体来联合定义。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值