Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Алгоритмы и структуры данных.doc
Скачиваний:
0
Добавлен:
01.03.2025
Размер:
1.14 Mб
Скачать

4.3Генерация перестановок за одну транспозицию элементов

Алгоритм генерирования перестановок, требующий одну транспозицию для получения очередной перестановки, реализуется рекурсивным образом с помощью процедуры Perm, содержащей один параметр - количество первых элементов массива P, для которых выполняется перестановка.

Пусть массив P, содержит последовательность вида:

P[1]

P[2]

P[3]

P[m-3]

P[m-2]

P[m-1]

P[m]

a1

a2

a3

am-3

am-2

am-1

am

Задачей процедуры Perm(n) является генерирование всех перестановок элементов

P[1], …, P[n]

через последовательное генерирование блока всех перестановок элементов

P[1], …, P[n-1]

при фиксированном элементе P[n] с последующей транспозицией элемента P[n] и одного из элементов

P[1], …, P[n‑1]

Пусть необходимо сгенерировать блок перестановок из m<=n элементов. При заданном P[m] генерируется блок перестановок из (m-1)! перестановок элементов P[1], …, P[m-1]. После этого определяется элемент из P[1], …, P[m-1], для которого выполняется транспозиция с элементом P[m].

Пусть задана последовательность 1, 2, 3, 4 и следующий набор перестановок для этой последовательности. Для каждой перестановки в этой последовательности выделена пара элементов, которые подвергаются транспозиции на каждом шаге генерации очередной перестановки.

1 2 3 4

2 1 3 4

2 3 1 4

3 2 1 4

3 1 2 4

1 3 2 4

4 3 2 1

3 4 2 1

3 2 4 1

2 3 4 1

2 4 3 1

4 2 3 1

4 1 3 2

1 4 3 2

1 3 4 2

3 1 4 2

3 4 1 2

4 3 1 2

(Обратить внимание на перестановку элементов 2 и 3)

4 2 1 3

2 4 1 3

2 1 4 3

1 2 4 3

1 4 2 3

4 1 2 3

На основе анализа приведенного примера можно предложить алгоритм выбора элемента из

P[1], …, P[m-1]

для которого выполняется транспозиция с элементом P[m]. Этот алгоритм позволяет находить соответствующий индекс B(m, i), где P[B(m, i)]  {P[1], …, P[m‑1]} и 1 <= i < m <= n.

В работе алгоритма различаются два случая, когда m – длина блока, четно и нечетно:

  • если m - нечетно, то после генерации очередного блока из (m-1)! перестановок для каждого i, 1 =< i <= m-1, выполняется перестановка P[B(m, i)] и P[m], где B(m, i) = m-1.

  • если m - четно, то, после генерации очередного блока из (m-1)! перестановок, для каждого i, 1 =< i <= m-1, выполняется перестановка P[B(m, i)] и P[m], где B(m, i) = i. Таким образом, содержимое P[m] последовательно меняется с содержимым P[1], P[2], …, P[m-2], P[m-1] (исключение составляет случай i = m-1 см. пример)

Процедура B имеет вид:

function B (M, I: integer): integer;

begin

if (M mod 2 = 0) and (M > 2) then

if I < M-1 then B := I

else B := M –2 {см. пример отмеченный случай перестановки элементов 2 и3}

else B := M-1;

end; {B}

Рассмотрим суть алгоритма генерации перестановок. Пусть элементы массива P образуют возрастающую последовательность натуральных чисел, т. е. P[i] = ai = i, где 1<=i<=m. Через ai обозначим элемент массива P[i].

Пусть m нечетно. Очередной вызов процедуры Perm(m-1), т. е. m-1 – четно, фактически выполняет циклический сдвиг на одну позицию в право последовательности P[1], P[2], …, P[m-2], P[m‑1] (см. случай, когда m четно). После вызова этой процедуры выполняется транспозиция элементов P[m] и P[m‑1]. В результате для каждого i, 1 =< i <= m-1, вызов процедуры Perm(m-1) в P[m] последовательно размещаются значения элементов

am, am-2, am-3, …, a2, a1, am-1

Бросается в глаза, что элемент am-1 попадет в позицию P[m] последним. Это следствие того, что сдвиг элементов массива выполняется до транспозиции элементов P[m] и P[m‑1]. Например, если массив содержит последовательность 1, 2, 3, 4, 5, то после первого вызова (i=1) процедуры Perm(5) эта последовательность изменится на 4, 1, 2, 5, 3.

Пусть m четно. Очередной вызов процедуры Perm(m-1) выполняет транспозицию элементов P[m] и P[i], для каждого i, 1 =< i <= m-1. Например, если массив содержит последовательность 1, 2, 3, 4, то после первого вызова (i=1) процедуры Perm(4) эта последовательность изменится на 4, 1, 2, 3.

Программа, реализующая данный алгоритм, имеет вид:

program Permutation3;

uses crt;

const N = 4;

var

I: integer;

Arr: array [1..N] of integer;

function B (M, I: integer): integer;

begin

if (M mod 2 = 0) and (M > 2) then

if I < M-1 then B := I

else B := M –2 {см. пример отмеченный случай перестановки элементов 2 и3}

else B := M-1;

end; {B}

procedure Perm (M: integer);

var I, J, Work: integer;

begin

if M = 1 then

begin

for J := 1 to N do Write (Arr[J], ' ');

Writeln;

end

else

for I := 1 to M do

begin

Perm (M-1);

if I < M then

begin

Work := Arr[B(M, I)];

Arr[B(M, I)] := Arr[M];

Arr[M] := Work;

end;

end;

end; {Perm}

begin

Clrscr;

for I := 1 to N do Arr [I] := I;

Perm (N);

end. { Permutation3}