C ++ STL下一代排列组合

时间:2016-05-18 21:50:06

标签: c++ algorithm stl combinations permutation

我知道我可以在包含元素std::next_permutation的某个容器上使用[1, 2, 3],这将生成此序列的6种排列。我想要做的是给出一些集合[1, 2, 3, 4, 5, 6]生成大小为3的所有可能的排列。因此,对于这个例子,[4, 3, 2]将是由此标准产生的排列之一。我正在寻找一种STL方式(如果可能的话),而不是编写我自己的组合函数。我应该阅读的任何特定的STL实现?

3 个答案:

答案 0 :(得分:3)

目前(截至2016年)没有单一的STD功能可以做到这一点。您最接近的是来自http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2639.pdf

的提案

您想要的功能称为next_partial_permutation,看起来像(来自N2639):

template  <class  BidirectionalIterator >
bool next_partial_permutation(
  BidirectionalIterator  first ,
  BidirectionalIterator  middle ,
  BidirectionalIterator  last)
{
  std::reverse(middle , last);
  return std::next_permutation(first , last);
}

答案 1 :(得分:2)

这不是最有效的算法,但它很容易。您必须从排序的元素开始。为了获得下一个k-置换,反转最后的n-k个元素,然后尝试获得下一个置换。前k个元素是下一个k-排列。

答案 2 :(得分:1)

这是一个用Smalltalk编写的算法。

该算法的思想是考虑长度为m的数组的词典顺序,其中的元素位于1n之间。鉴于任何此类array,方法next会将array替换为所述顺序中的下一个部分排列。

我创建了一个包含三个实例变量的类

array       the current permutation of length m
m           the size of array
complement  the SortedCollection of integers not in array

实例创建方法m:n:的工作原理如下

m: length n: limit
  m := length.
  array := (1 to: m) asArray.
  complement := (m + 1 to: limit) asSortedCollection

在此课程中,方法next会修改array,以便它现在可以保留下一个排列。

值得一提的是,该算法不是递归的。

方法nextnil回答iff array包含订单中的最后一个排列(即array = (n, n-1, ...., n-m+1)

要计算所有排列,请从array = (1 ... m)开始,然后发送next,直到答案为nil

next
  | index max h a c |
  index := self lastDecreasingIndex.
  max := complement max.
  h := (index to: m) findLast: [:i | (array at: i) < max] ifAbsent: nil.
  h isNil
    ifTrue: [
      index = 1 ifTrue: [^nil].
      a := array at: index - 1.
      index to: m do: [:i | complement add: (array at: i)].
      c := complement detect: [:cj | a < cj].
      array at: index - 1 put: c.
      complement remove: c; add: a.
      index to: m do: [:i | array at: i put: complement removeFirst]]
    ifFalse: [
      h := h + index - 1.
      a := array at: h.
      c := complement detect: [:ci | a < ci].
      array at: h put: c.
      complement remove: c; add: a.
      h + 1 to: m do: [:i | complement add: (array at: i)].
      h + 1 to: m do: [:i | array at: i put: complement removeFirst]]

其中

lastDecreasingIndex
  | index |
  index := m.
  [(array at: index - 1) > (array at: index)] whileTrue: [
    index := index - 1.
    index = 1 ifTrue: [^1]].
  ^index