`

STL next_permutation 简单剖析

    博客分类:
  • C++
J# 
阅读更多

今天想学学全排列的非递归实现,但是搜索了半天,都是转载的同一篇文章,这篇文章的规律我还是没看懂。

想到c++的STL里有一个next_permutation()可以实现产生比当前序列大一点的下一个序列。

通过这种方法,也可以实现全排列的非递归实现。

 

STL源码下载:http://www.sgi.com/tech/stl/download.html

 

next_permutation()的原函数位于:stl_alog.h里面

内容如下:

// next_permutation and prev_permutation, with and without an explicitly 
// supplied comparison function.

template <class _BidirectionalIter>
bool next_permutation(_BidirectionalIter __first, _BidirectionalIter __last) {
  __STL_REQUIRES(_BidirectionalIter, _BidirectionalIterator);
  __STL_REQUIRES(typename iterator_traits<_BidirectionalIter>::value_type,
                 _LessThanComparable);
  if (__first == __last)
    return false;
  _BidirectionalIter __i = __first;
  ++__i;
  if (__i == __last)
    return false;
  __i = __last;
  --__i;

  for(;;) {
    _BidirectionalIter __ii = __i;
    --__i;
    if (*__i < *__ii) {
      _BidirectionalIter __j = __last;
      while (!(*__i < *--__j))
        {}
      iter_swap(__i, __j);
      reverse(__ii, __last);
      return true;
    }
    if (__i == __first) {
      reverse(__first, __last);
      return false;
    }
  }
}

 

基本思想如下:

从最后每相邻的两个进行比较,如果有前面一个比后面的小(i为较小位置,ii,为较大位置),那么此时一定存在一个排列比当前的大,然后是怎么产生这下一个排列。应该找这个较小的数的后面从最后开始比它大的第一个数,将它换到当前较小的位置上,然后将较大数ii到最后进行逆序。这样就产生了下一个排列。原理类似于,找到下一个较大的作为开始位的数,然后将后面的数字从最小开始即升序,例如原来为4653转换后为:5346

next_permutation()
{
        if  no element || only one element
               return false;

        i = last_element_ptr
        while(true)
        {
                 ii = i;    // the element before i
                 --i;
                 if  *i < *ii   // then there must be a sequence to change
                 {
                        j =  last_element_ptr
                        while( !(*i<*--j)   //find the first element from tail to head
                        {}                      //which is bigger than *i
                        swap(i, j)            // swap the  elements which i and j point to.
                         reverse(ii, last_element_ptr)  // reverse the array
                        return true;
                }
                if i == first_element_ptr   // if we to the head of the array, so no permutation
                {
                        reverse(first_element_ptr, last_element_ptr)
                        return false
                 }
         }


}
 

      从stl的next_permutation源码中我们看到,对于一个已经是最大权值的序列(即没有下一个比当前值大的排列),虽然返回值是false,但是它仍就将序列进行了逆序,例如对4321使用next_permutation后,序列变为1234.

看来读读久经考验的源代码是大有好处的。

 

      由此,我们就可以实现非递归的全排列了。呵呵 ,不用多说了吧。

 

 

 

 

 

 

分享到:
评论

相关推荐

    排列_next_permutation1

    next_permutation 函数是 C++/STL 中定义的函数之一,它可以生成给定序列的下一个较大的排列。prev_permutation 函数则是生成给定序列的上一个较小的排列。二者的原理相同,仅遍例顺序相反。 为了生成下一个较大的...

    STL源码剖析与算法详解

    本PDF书籍深入分析了STL(标准模板库)的各项特性和源码实现,涵盖了类型技术、内存管理、常见算法与数据结构等内容,具体讲解了一系列高级实现技术如STL各种容器(如向量、列表、树、队列等)、RB树结构以及众多...

    STL源码剖析.pdg

    6.7.5 next_permutation 380 6.7.6 prev_permutation 382 6.7.7 random_shuffle 383 6.7.8 partial_sort / partial_sort_copy 386 6.7.9 sort 389 6.7.10 equal_range(应用于有序区间) 400 6.7.11 inplace_...

    acm ————stl

    - 使用`std::next_permutation`函数生成所有可能的排列组合。 - 输出所有合法的仓库访问序列。 3. **代码实现**(示例代码片段): ```cpp #include #include #include using namespace std; int main...

    算法实验源代码

    通过对以上两个代码示例的分析,我们可以看到STL提供的工具不仅方便高效,而且功能强大。无论是向量容器的操作还是全排列的生成,都展示了STL的强大能力及其在实际编程中的应用价值。掌握这些技术对于提高编程效率、...

    STL 源码剖析(侯捷先生译著)

    6.7.5 next_permutation 380 6.7.6 prev_permutation 382 6.7.7 random_shuffle 383 6.7.8 partial_sort / partial_sort_copy 386 6.7.9 sort 389 6.7.10 equal_range(应用于有序区间) 400 6.7.11 inplace_...

    C++ STL开发技术导引(第5章)

    第5章 C++ STL泛化技术分析 58 5.1 算法和迭代器 58 5.1.1 算法 58 5.1.2 迭代器 61 5.1.3 函数对象 65 5.1.4 适配器 68 5.2 内存分配器和容器 74 5.2.1 内存分配器 75 5.2.2 容器 77 5.3 概念 ...

    C++ STL 开发技术导引(第6章)

    第5章 C++ STL泛化技术分析 58 5.1 算法和迭代器 58 5.1.1 算法 58 5.1.2 迭代器 61 5.1.3 函数对象 65 5.1.4 适配器 68 5.2 内存分配器和容器 74 5.2.1 内存分配器 75 5.2.2 容器 77 5.3 概念 ...

    C++ STL开发技术导引(第3章)

    第5章 C++ STL泛化技术分析 58 5.1 算法和迭代器 58 5.1.1 算法 58 5.1.2 迭代器 61 5.1.3 函数对象 65 5.1.4 适配器 68 5.2 内存分配器和容器 74 5.2.1 内存分配器 75 5.2.2 容器 77 5.3 概念 ...

    全排列算法解析(完整版)

    在C++中,标准模板库(STL)提供了next_permutation()函数,可以用来直接生成下一个排列,极大地方便了排列组合的算法实现。 对于时间复杂度,全排列算法至少是O(n!)的复杂度,因为需要生成所有可能的排列组合。...

    叶倩琳 201706061330 实验一1

    而使用非递归的STL库函数`next_permutation`,它通过迭代方式避免了重复计算,直接生成下一个排列,时间复杂度为O(n*n!),在实际操作中,对于较大的n,非递归方法通常比递归方法更快。5、实验体会递归算法虽然在逻辑...

    algorithm 头文件 说明

    18. next_permutation和prev_permutation:改变序列的排列顺序到下一个或上一个排列。 19. nth_element:重新排序序列,使得第n个位置的元素是它最终排序位置的元素。 20. partial_sort和partial_sort_copy:对...

    one.rar_数据结构_Visual_C++_

    同时,我们可以利用C++的迭代器或者算法库中的函数,如next_permutation,来生成和处理全排列。 接下来,"one.cpp"的代码可能包含以下步骤: 1. 创建一个大小为256的vector,初始化为0到255的序列。 2. 使用next_...

    -C++参考大全(第四版) (2010 年度畅销榜

    40.6 一个简单的表达式分析器 40.7 向分析器中添加变量 40.8 递归下降分析器中的语法检查 40.9 构建一个通用的分析器 40.10 需要试验的一些东西 附录A C++的.NET可管理扩展 附录B C++和机器人时代

    C++与操作系统等面试题97

    - 示例:`std::next_permutation(begin(v), end(v));` 7. **分割(Partition)**: - 功能:根据谓词将元素重新排列成两个部分。 - 示例:`std::partition(begin(v), end(v), predicate);` 8. **随机排列...

    最好的ACM模板,注释很好

    - **下一个排列**:`next_permutation()`。 - **次序元素**:`nth_element()`。 - **部分排序**:`partial_sort()`。 - **部分排序拷贝**:`partial_sort_copy()`。 - **部分累加**:`partial_sum()`。 - **前一个...

    ACM程序设计常用算法与数据结构参考

    - **next_permutation()/nth_element()**:用于生成序列的下一个排列、将第n个元素放在正确位置等。 - **partial_sort()/partial_sort_copy()**:用于部分排序序列或拷贝序列的一部分。 - **partial_sum()/prev_...

Global site tag (gtag.js) - Google Analytics