Участник:ZeRoGerc — различия между версиями
ZeRoGerc (обсуждение | вклад) (→Псевдокод) |
ZeRoGerc (обсуждение | вклад) (→Доказательство корректности) |
||
Строка 30: | Строка 30: | ||
== Доказательство корректности == | == Доказательство корректности == | ||
− | Очевидно что требование о том что каждая генерируемая перестановка отличается от предыдущей транспозицией двух соседних элементов выполнено исходя из самого алгоритма. Осталось доказать, что таким образом мы сгенерируем все перестановки. Будем использовать | + | Очевидно что требование о том что каждая генерируемая перестановка отличается от предыдущей транспозицией двух соседних элементов выполнено исходя из самого алгоритма. Осталось доказать, что таким образом мы сгенерируем все перестановки. |
+ | |||
+ | Будем использовать обозначения: | ||
+ | *<tex>(a,</tex> ←<tex>)</tex> - элемент с заданным направлением(компонента). | ||
+ | *<tex>P[i]</tex> - перестановка с номером <tex>i</tex> | ||
+ | |||
+ | |||
{{Утверждение | {{Утверждение | ||
|id=id1 | |id=id1 | ||
|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> | ||
}} | }} |
Версия 11:27, 28 ноября 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 элементом по направлению стелки }
Доказательство корректности
Очевидно что требование о том что каждая генерируемая перестановка отличается от предыдущей транспозицией двух соседних элементов выполнено исходя из самого алгоритма. Осталось доказать, что таким образом мы сгенерируем все перестановки.
Будем использовать обозначения:
- ← - элемент с заданным направлением(компонента).
- - перестановка с номером
Утверждение: |
Число в перестановке не является подвижным элементом тогда и толко тогда когда первая компонента перестановки есть ← или последняя компонента есть → |