На этом шаге мы рассмотрим алгоритмы, используемые для перестановки элементов.
Для выполнения перестановки элементов существуют следующие алгоритмы:
bool next_permutation (BidirectionalIterator beg, BidirectionalIterator end) bool prev_permutation (BidirectionalIterator beg, BidirectionalIterator end)
Алгоритм next_permutation() изменяет порядок следования элементов в интервале [beg,end) в соответствии со следующей перестановкой.
Алгоритм prev_permutation() изменяет порядок следования элементов в интервале [beg,end) в соответствии с предыдущей перестановкой.
Оба алгоритма возвращают false, если элементы находятся в "нормальном" (лексикографическом) порядке, то есть упорядочены по возрастанию для next_ permutation() или по убыванию для prev_permutation(). Следовательно, для того чтобы перебрать все перестановки, нужно отсортировать элементы (по возрастанию или убыванию) и организовать цикл, который вызывает алгоритм next_ permutation() или prev_permutation() до тех пор, пока алгоритм возвращает true.
Сложность линейная (не более numberOfElements/2 обменов).
Следующий пример показывает, как при помощи алгоритмов next_permutation() и prev_permutation() генерируются все перестановки элементов:
//--------------------------------------------------------------------------- #include <vcl.h> #include <iterator> #include "algostuff.hpp" #include <conio.h> //необходимо для getch() #pragma hdrstop //--------------------------------------------------------------------------- #pragma argsused using namespace std; std::string ToRus(const std::string &in) { char *buff = new char [in.length()+1]; CharToOem(in.c_str(),buff); std::string out(buff); delete [] buff; return out; } int main() { vector<int> coll; INSERT_ELEMENTS(coll,1,3); PRINT_ELEMENTS(coll,"Исходный вектор:\n"); // Генерировать перестановки элементов до тех пор, пока они // не будут упорядочены // - при этом перебираются все возможные перестановки, // - потому что в исходном состоянии // - элементы упорядочены по возрастанию cout << ToRus("Перестановки:\n"); while (next_permutation(coll.begin(),coll.end())) { PRINT_ELEMENTS(coll," "); } PRINT_ELEMENTS(coll,"Исходная перестановка:\n"); // Генерировать перестановки элементов до тех пор, // пока элементы не будут упорядочены по убыванию // - это будет следующая перестановка после сортировки // - по возрастанию, поэтому цикл сразу же завершается while (prev_permutation(coll.begin(),coll.end())) { PRINT_ELEMENTS(coll," "); } PRINT_ELEMENTS(coll,"Конечная перестановка:\n"); // Генерировать перестановки элементов до тех пор, // пока элементы не будут упорядочены по убыванию // - при этом перебираются все возможные перестановки, // - потому что в исходном состоянии // - элементы упорядочены по убыванию while (prev_permutation(coll.begin(),coll.end())) { PRINT_ELEMENTS(coll," "); } PRINT_ELEMENTS(coll,"Перестановка:\n"); getch(); return 0; } //---------------------------------------------------------------------------
Результат выполнения программы выглядит так:
Рис.1. Результат выполнения приложения
На следующем шаге мы рассмотрим перестановку элементов в случайном порядке.