Алгоритмы порождения перестановок

Также как и при генерации сочетания будем считать, что элементами множества являются целые числа от 1 до n.

Последовательность перестановок на множестве {1,2,...,n} представлена в лексикографическом порядке, если она записана в порядке возрастания получающихся чисел. Например, лексикографическая последовательность перестановок трех элементов имеет вид 123, 132, 213, 231, 312, 321.

Порождать такую последовательность можно следующим образом. Начиная с перестановки Р=(1,2,...,n), переходим к следующей, путем просмотра текущей справа налево с целью поиска самой правой позиции, в которой рi<рi+1. Найдя ее, ищем рj, наименьший элемент, расположенный справа от рi и больше его. Затем осуществляется транспозиция элементов рi и pj и отрезок рi+1,...,рn (элементы которого расположены в порядке убывания) переворачивается. Например, для n=8 имеем текущую перестановку p=(2,6,5,8,7,4,3,1), тогда рi=5 (i=3) и рj=7 (j=5). Меняя их местами и переворачивая p4,p5,p6,p7,p8, получаем следующую перестановку (2,6,7,1,3,4,5,8). Эту процедуру реализует алгоритм представленный на рис.2.8.

Рассмотрим еще один алгоритм порождения перестановок. Этот алгоритм генерирует перестановки в порядке минимального изменения, т.е. перестановка отличается от предшествующей транспозицией двух соседних элементов.

Такую последовательность перестановок можно построить рекурсивно. Для n=1 существует единственная перестановка (1). Предположим, что построена последовательность перестановок П12,...,П(n-1)! на множестве {1,2,...,n-1} в порядке минимального изменения.

 
 

 


Расширим каждую из (n-1)! этих перестановок путем вставки элемента n на каждое из n возможных мест. Причем, элемент n добавляется к Пi последовательно во все позиции справа налево, если i нечетное, и слева направо, если i четное. Пример такого расширения представлен на рис .2.9.

Эту же последовательность перестановок можно порождать итеративно, получая каждую перестановку из предшествующей и добавочной информации. Это делается с помощью трех векторов: текущей перестановки Р=(р1,...,рn), обратной к ней перестановки 0=(о1,...,оn) (о1 - индекс наименьшего элемента в Р, о2 - индекс следующего по величине элемента в Р и т.д., следовательно, ) и записи направления D=(d1,...,dn), в котором сдвигаются элементы перестановки (di=-1, если pi сдвигается влево, di=1 - вправо, di=0 - не сдвигается). Элемент сдвигается до тех пор, пока не достигнет элемента большего чем он сам; в этом случае сдвиг прекращается. В этот момент направление сдвига данного элемента изменяется на противоположное и передвигается следующий меньший его элемент, который можно сдвинуть. Поскольку хранится перестановка, обратная к Р, то в Р легко найти место следующего меньшего элемента. Эту процедуру реализует алгоритм представленный на рис.2.10.

Заметим, что в данном алгоритме Р0 и Pn+1 инициализируются величиной n+1, чтобы прекратить передвижение n, и d1 инициализируется нулем, чтобы в тех случаях, когда m становятся равным единице во внутреннем цикле, остаток внешнего цикла был правильно определен.

Алгоритм порождения случайных перестановок представлен на рис.2.11. Данный алгоритм аналогичен алгоритму порождения случайных сочетаний (рис.2.7).