C++ STL Next Permutation with Combination

一世执手 提交于 2019-12-21 09:30:10

问题


I know that I can use std::next_permutation on some container containing the elements [1, 2, 3] which would generate 6 permutations of this sequence. What I would like to do is given some set [1, 2, 3, 4, 5, 6] generate all possible permutations of size 3. So for this example, [4, 3, 2] would be one of the permutations resulting from this criteria. I'm looking for an STL way of doing this (if possible) rather than writing my own combinations function. Any particular STL implementation I should be reading about ?


回答1:


There is currently (as of 2016) no single STD function to do that. The closest you have is the proposal from http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2639.pdf

The function you want is called next_partial_permutation and looks like (from N2639):

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



回答2:


This is not the most efficient possible algorithm but it's easy. You must start with the elements sorted. To get the next k-permutation, reverse the last n-k elements and then try to get the next permutation. The first k elements are the next k-permutation.




回答3:


Here is an algorithm written in Smalltalk.

The idea of the algorithm is to consider the lexicographic order of arrays of length m with elements between 1 and n. Given any such array, the method next replaces array with its next partial permutation in said order.

I've created a class with three instance variables

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

The instance creation method m:n: works as follows

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

In this class the method next modifies the array so that it will now hold the next permutation.

It might be worth mentioning that the algorithm is not recursive.

The method next answers with nil iff array contains the last permutation in the order (i.e., array = (n, n-1, ...., n-m+1).

To compute all permutations start with array = (1 ... m) and send next until the answer is 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]]

Where

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


来源:https://stackoverflow.com/questions/37310678/c-stl-next-permutation-with-combination

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!