Коды Грея для перестановок — различия между версиями
ZeRoGerc (обсуждение | вклад) |
ZeRoGerc (обсуждение | вклад) (→Псевдокод получения кода Грея) |
||
| Строка 55: | Строка 55: | ||
gray_code(n): | gray_code(n): | ||
| − | '''if''' n == 1 | + | '''if''' n == 1 |
| − | '''return''' [{1}] <font color=darkgreen>// возращаем список из одной перестановки</font color=darkgreen> | + | '''return''' [{1}] <font color=darkgreen> //возращаем список из одной перестановки</font color=darkgreen> |
| − | '''else''' | + | '''else''' |
| − | result = [] <font color=darkgreen>// пустой список</font color=darkgreen> | + | result = [] <font color=darkgreen> //пустой список</font color=darkgreen> |
| − | perms = gray_code(n - 1) <font color=darkgreen>// perms {{---}} перестановки из n - 1 элемента</font color=darkgreen> | + | perms = gray_code(n - 1) <font color=darkgreen> //perms {{---}} перестановки из n - 1 элемента</font color=darkgreen> |
| − | backward = false <font color=darkgreen>// переменная которая говорит с какой стороны заполнять перестановку</font color=darkgreen> | + | backward = false <font color=darkgreen> //переменная которая говорит с какой стороны заполнять перестановку</font color=darkgreen> |
| − | '''for''' perm in perms | + | '''for''' perm in perms <font color=darkgreen> //perm {{---}} текущая перестановка</font color=darkgreen> |
| − | '''if''' backward | + | '''if''' backward |
| − | current = concat(perm, {n})<font color=darkgreen>// дописываем {n} в конец perm</font color=darkgreen> | + | current = concat(perm, {n})<font color=darkgreen> //дописываем {n} в конец perm</font color=darkgreen> |
| − | result.append(current)<font color=darkgreen>// добавляем в ответ перестановку current</font color=darkgreen> | + | result.append(current)<font color=darkgreen> //добавляем в ответ перестановку current</font color=darkgreen> |
| − | '''for''' (i = n; i > 1; i--) | + | '''for''' (i = n; i > 1; i--) |
| − | swap(current[i - 1], current[i])<font color=darkgreen>//переставляем n</font color=darkgreen> | + | swap(current[i - 1], current[i])<font color=darkgreen> //переставляем n</font color=darkgreen> |
| − | result.append(current) <font color=darkgreen>//добавляем в ответ перестановку current</font color=darkgreen> | + | result.append(current) <font color=darkgreen> //добавляем в ответ перестановку current</font color=darkgreen> |
| − | '''else''' | + | '''else''' |
| − | current = concat({n}, perm) <font color=darkgreen>// дописываем {n} в начало perm</font color=darkgreen> | + | current = concat({n}, perm) <font color=darkgreen> //дописываем {n} в начало perm</font color=darkgreen> |
| − | result.append(current) <font color=darkgreen>//добавляем в ответ перестановку current</font color=darkgreen> | + | result.append(current) <font color=darkgreen> //добавляем в ответ перестановку current</font color=darkgreen> |
| − | '''for''' (i = 1; i < n; i++) | + | '''for''' (i = 1; i < n; i++) |
| − | swap(current[i], current[i + 1]) <font color=darkgreen>//переставляем n</font color=darkgreen> | + | swap(current[i], current[i + 1]) <font color=darkgreen> //переставляем n</font color=darkgreen> |
| − | result.append(current) <font color=darkgreen>//добавляем в ответ перестановку current</font color=darkgreen> | + | result.append(current) <font color=darkgreen> //добавляем в ответ перестановку current</font color=darkgreen> |
| − | backward = !backward <font color=darkgreen>//меняем состояние backward</font color=darkgreen> | + | backward = !backward <font color=darkgreen> //меняем состояние backward</font color=darkgreen> |
'''return''' result <font color=darkgreen>//возвращаем ответ в виде списка</font color=darkgreen> | '''return''' result <font color=darkgreen>//возвращаем ответ в виде списка</font color=darkgreen> | ||
Версия 23:09, 6 декабря 2014
Коды Грея для перестановок(англ. Gray code for permutation) — упорядочение перестановок, при котором соседние перестановки отличаются только элементарной транспозицией.
Элементарная транспозиция(англ. Adjacent transposition) — перестановка местами двух соседних элементов.
Содержание
Построение кода Грея для перестановок
Будем строить код Грея для длины . Предположим, что нам известен код Грея для перестановок длиной . Возьмем первую перестановку из известного нам кода. Она имеет следующий вид:
Сначала запишем число в начало этой перестановки, после чего будем двигать его вправо элементарными транспозициями (подчёркнуты пары переставляемых элементов).
Получим различных перестановок, отличающихся одной элементарной транспозицией. Возьмем следующую перестановку из кода Грея для перестановок длины и припишем в конце число . Эта перестановка отличается на одну элементарную транспозицию (последние элементы совпадают, а префиксы длины отличаются на элементарную транспозицию). Пусть она имеет следующий вид:
Элемент записываем в конец и начинаем "двигать" его влево:
Продолжаем аналогично. Для каждой перестановки дописываем в один конец (поочерёдно), и с помощью элементарных транспозиций двигаем в другой конец, при этом добавляя каждую промежуточную перестановку в список.
Таким образом получаем для каждой перестановки длиной (всего штук) по новых перестановок, в сумме перестановок. Все они различны, так как для любых двух перестановок из нового кода Грея элемент стоит на разных позициях,а если стоит на одной и той же позиции, то эти перестановки образованы от разных перестановок длиной . Так же все соседние перестановки отличаются ровно в одной элементарной транспозиции. Итого, мы получили список из различных перестановок длиной , причём соседние отличаются в одной элементарной транспозиции.
Пример применения алгоритма
Рассмотрим код Грея для длины :
Тогда следуя алгоритму полученный код будет выглядеть так (подчёркнуты пары переставляемых элементов):
- — берем первую перестановку и добавляем в начало тройку
- — двигаем до последней позиции
- — берем следующую перестановку и записываем тройку в конец
- — двигаем в начало
Код Грея получен.
Псевдокод получения кода Грея
Получаем код Грея рекурсивно, в базовом случае возвращаем список из одной перестановки .
gray_code(n):
if n == 1
return [{1}] //возращаем список из одной перестановки
else
result = [] //пустой список
perms = gray_code(n - 1) //perms — перестановки из n - 1 элемента
backward = false //переменная которая говорит с какой стороны заполнять перестановку
for perm in perms //perm — текущая перестановка
if backward
current = concat(perm, {n}) //дописываем {n} в конец perm
result.append(current) //добавляем в ответ перестановку current
for (i = n; i > 1; i--)
swap(current[i - 1], current[i]) //переставляем n
result.append(current) //добавляем в ответ перестановку current
else
current = concat({n}, perm) //дописываем {n} в начало perm
result.append(current) //добавляем в ответ перестановку current
for (i = 1; i < n; i++)
swap(current[i], current[i + 1]) //переставляем n
result.append(current) //добавляем в ответ перестановку current
backward = !backward //меняем состояние backward
return result //возвращаем ответ в виде списка
Примеры кодов Грея для перестановок
Перестановки для n = 2
| Номер | Перестановка |
|---|---|
Перестановки для n = 3
| Номер | Перестановка |
|---|---|
Сведение задачи построения кода Грея для перестановок к графам
Последовательность перестановок, полученная с помощью данного алгоритма имеет интересную интерпретацию. Так, если рассмотреть граф, вершины которого соответствуют всем перестановкам и в котором две вершины, соответствующие перестановкам и , соединены ребром, если образуется из однократной транспозицией соседних элементов, то полученная последовательность является гамильтоновым путем в этом графе.
См. также
Источники информации
- Романовский И.В. Дискретный Анализ - "Санкт-Петербург", 2003. - стр. 39-41 - ISBN 5-94157-330-8