C++ STL Следующая перестановка с комбинацией

Я знаю, что я могу использовать std::next_permutation на некотором контейнере, содержащем элементы [1, 2, 3] который будет генерировать 6 перестановок этой последовательности. То, что я хотел бы сделать, это дать некоторый набор [1, 2, 3, 4, 5, 6] генерировать все возможные перестановки размера 3. Так что для этого примера [4, 3, 2] будет одной из перестановок, вытекающих из этого критерия. Я ищу STL способ сделать это (если это возможно), а не писать свою собственную функцию комбинации. О какой-то конкретной реализации STL, о которой я должен читать?

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);
}

Это не самый эффективный алгоритм, но он прост. Вы должны начать с отсортированных элементов. Чтобы получить следующую k-перестановку, поменяйте местами последние nk элементов и затем попытайтесь получить следующую перестановку. Первые k элементов являются следующей k-перестановкой.

Вот алгоритм, написанный на Smalltalk.

Идея алгоритма состоит в том, чтобы рассмотреть лексикографический порядок массивов длины m с элементами между 1 а также n, Учитывая любой такой 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 так что теперь он будет содержать следующую перестановку.

Возможно, стоит упомянуть, что алгоритм не является рекурсивным.

Метод next ответы с nil тогда и только тогда 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
Другие вопросы по тегам