Участник:ZeRoGerc — различия между версиями
ZeRoGerc (обсуждение | вклад) |
ZeRoGerc (обсуждение | вклад) (→Доказательство корректности) |
||
Строка 35: | Строка 35: | ||
*<tex>(a,</tex> ←<tex>)</tex> - элемент с заданным направлением(компонента). | *<tex>(a,</tex> ←<tex>)</tex> - элемент с заданным направлением(компонента). | ||
*<tex>P[i]</tex> - перестановка с номером <tex>i</tex> | *<tex>P[i]</tex> - перестановка с номером <tex>i</tex> | ||
+ | *<tex>P[i]\backslash\{a\}</tex> - перестановка с номером <tex>i</tex> без элемента <tex>a</tex> | ||
{{Утверждение | {{Утверждение | ||
|id=approval1 | |id=approval1 | ||
− | |statement=Число <tex>n</tex> в перестановке не является подвижным элементом тогда и толко тогда когда первая компонента перестановки есть <tex>(n,</tex> ←<tex>)</tex> или последняя компонента есть <tex>(n,</tex> →<tex>)</tex> | + | |statement=Число <tex>n</tex> в перестановке не является подвижным элементом тогда и толко тогда когда первая компонента перестановки есть <tex>(n,</tex> ←<tex>)</tex> или последняя компонента есть <tex>(n,</tex> →<tex>)</tex>. |
}} | }} | ||
Строка 45: | Строка 46: | ||
{{Лемма | {{Лемма | ||
|id=lemma1 | |id=lemma1 | ||
− | |statement=Если в перестановке <tex>P[i]</tex> есть подвижный элемент <tex>a \neq n</tex> то также определены перестановки <tex>P[i + 1] ... P[i + n]</tex> причём <tex>P[]</tex> | + | |statement=Если в перестановке <tex>P[i]</tex> есть подвижный элемент <tex>a \neq n</tex> то также определены перестановки <tex>P[i + 1] ... P[i + n]</tex> причём <tex>P[i + 1]\backslash\{n\} = P[i + 2]\backslash\{n\} = ... = P[i + n]\backslash\{n\}</tex>. |
− | |proof= | + | |proof= |
}} | }} |
Версия 18:30, 29 ноября 2014
Алгоритм Джонсона-Троттера(англ. Johnson-Trotter algorithm) - алгоритм генерации всех перестановок из
элементов. Причём любая перестановка отличаются от предыдущей транспозицией двух соседних элементов.Идея
Сопоставим каждому элементу перестановки
направление . Будем указывать направление при помощи стрелок ← ("влево") или →("вправо"). Назовём элемент подвижным, если по направлению стелки стоит элемент меньше его. Например для ←, →, ←, →, ← , подвижными являются элементы 3 и 5. На каждой итерации алгоритма будем искать наибольший подвижный элемент и менять местами с элементом, который стоит по направлению стрелки. После чего поменяем направление стрелок на противоположное у всех элементов больших текущего. Изначально ←, ... ,←Пример работы алгоритма для n = 3
- ←, ←, ←
- ←, ←, ←
- ←, ←, ←
- →, ←, ←
- ←, →, ←
- ←, ←, →
Псевдокод
//Элементы нумеруются начиная с 1 p = {1, ... , n} d = {←, ... , ←} while (true){ print(); // печатаем текущую перестановку id = -1; // индекс наибольшего подвижного элемента for i (1 .. n){ if (p[i] - подвижный) and ((id = -1) or (p[i] > p[id])) id = i } if (id = -1) break // не нашли подвижного элемента swap(id) //меняем элемент p[id], d[id] c элементом по направлению стелки }
Доказательство корректности
Очевидно что требование о том что каждая генерируемая перестановка отличается от предыдущей транспозицией двух соседних элементов выполнено исходя из самого алгоритма. Осталось доказать, что таким образом мы сгенерируем все перестановки.
Будем использовать обозначения:
- ← - элемент с заданным направлением(компонента).
- - перестановка с номером
- - перестановка с номером без элемента
Утверждение: |
Число в перестановке не является подвижным элементом тогда и толко тогда когда первая компонента перестановки есть ← или последняя компонента есть → . |
Лемма: |
Если в перестановке есть подвижный элемент то также определены перестановки причём . |