`next_permutation()` 函数在 C++ 中的内部是什么?

huangapple go评论71阅读模式
英文:

What is the internal of `next_permutation()` function in c++

问题

最近我解决了一个排列的问题。然后我搜索了一个库函数来解决这个问题。我找到了next_permutation函数。使用这个函数,我解决了问题。我搜索了很多以找出函数的内部工作原理,但我没有找到好的信息源。

vector<vector<int>> permute(vector<int>& nums) {
    sort(nums.begin(), nums.end());
    vector<vector<int>> v;
    do{
        v.push_back(nums);
    }while(next_permutation(nums.begin(), nums.end()));
    return v;
}

我想了解这个函数的内部工作原理。如果有人了解,请分享一下函数的代码。

英文:

Recently I solved a problem of permutation. Then I searched for library function for solve a the problem. I found next_permutation function. Using the function I Solved the problem. I searched a lot to find out the internal of the function but I did not find good sources.

 vector&lt;vector&lt;int&gt;&gt; permute(vector&lt;int&gt;&amp; nums) {
        sort(nums.begin(), nums.end());
        vector&lt;vector&lt;int&gt;&gt;v;
        do{
            v.push_back(nums);
        }while(next_permutation(nums.begin(), nums.end()));
        return v;
    }

I want to know about the internal of the function. If anyone know about it , please share a code for the function.

答案1

得分: 3

这是来自libstdc++的实现(与SGI STL中的相同),稍作简化和清理以提高可读性:

template&lt;typename BidirectionalIterator&gt;
bool next_permutation(BidirectionalIterator first, BidirectionalIterator last)
{
    if (first == last)
	    return false;
    BidirectionalIterator i = first;
    ++i;
    if (i == last)
	    return false;
    i = last;
    --i;

    for(;;)
	{
	    BidirectionalIterator ii = i;
	    --i;
	    if (*i &lt; *ii)
	    {
	        BidirectionalIterator j = last;
 	        while (!(*i &lt; *--j)) {}
	        std::swap(*i, *j);
	        std::reverse(ii, last);
	        return true;
	    }
	    if (i == __first)
	    {
	        std::reverse(first, last);
	        return false;
	    }
	}
}

这是一个众所周知的算法("Algorithm L"),请参阅D.E.Knuth的计算机编程艺术第4A卷中的第7.2.1.2节生成所有排列

该算法的思想是:对于当前排列,在右侧找到最长的递减子序列{...ap ≤ ai > aj > ... > ak},找到范围[i, k]内具有最大可能f的下一个前置元素af > ap,交换afap,然后将剩余元素按升序排列,即反转子序列{ai...ap...ak}

英文:

Here is the implementation from libstdc++ (same as in SGI STL) simplified and cleaned up a little bit for readability:

template&lt;typename BidirectionalIterator&gt;
bool next_permutation(BidirectionalIterator first, BidirectionalIterator last)
{
    if (first == last)
	    return false;
    BidirectionalIterator i = first;
    ++i;
    if (i == last)
	    return false;
    i = last;
    --i;

    for(;;)
	{
	    BidirectionalIterator ii = i;
	    --i;
	    if (*i &lt; *ii)
	    {
	        BidirectionalIterator j = last;
 	        while (!(*i &lt; *--j)) {}
	        std::swap(*i, *j);
	        std::reverse(ii, last);
	        return true;
	    }
	    if (i == __first)
	    {
	        std::reverse(first, last);
	        return false;
	    }
	}
}

This is a well-known algorithm ("Algorithm L"), see Sec. 7.2.1.2 Generating all permutations in The art of computer programming. Vol. 4A: Combinatorial algorithms, Part 1 by D.E.Knuth.

Idea of the algorithm: for the current permutation, find the longest decreasing subsequence on the right, {...ap ≤ ai &gt; aj &gt; ... &gt; ak}, find the next front element af &gt; ap with the largest possible f in the range [i, k], swap af and ap, and then put the remaining elements in the ascending order, i.e. reverse the subsequence {ai...ap...ak}.

huangapple
  • 本文由 发表于 2023年7月27日 22:27:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/76780731.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定