Блинная сортировка — различия между версиями
Строка 5: | Строка 5: | ||
Для начала покажем, что любую последовательность можно отсортировать с помощью блинной сортировки. Для этого будет предложен алгоритм, позволяющий отсортировать любой массив, сделав не более <tex>2n</tex> операций, где <tex>n</tex> {{---}} размер массива. | Для начала покажем, что любую последовательность можно отсортировать с помощью блинной сортировки. Для этого будет предложен алгоритм, позволяющий отсортировать любой массив, сделав не более <tex>2n</tex> операций, где <tex>n</tex> {{---}} размер массива. | ||
− | Найдём максимальный элемент последовательности с номером <tex>i</tex> и развернём префикс массива до <tex>i</tex>-ого элемента. Теперь максимальный элемент находится в начале массива. Развернём весь массив, теперь максимальный элемент находится в конце массива. Сделаем то же самое рекуррентно для префикса длины <tex>n-1</tex>. Переместим второй по возрастанию элемент в конец подотрезка, после чего последние два элемента будут отсортированы, и продолжим для префикса длины <tex>n-2</tex>. Таким образом, на каждой итерации мы сделаем | + | Найдём максимальный элемент последовательности с номером <tex>i</tex> и развернём префикс массива до <tex>i</tex>-ого элемента. Теперь максимальный элемент находится в начале массива. Развернём весь массив, теперь максимальный элемент находится в конце массива. Сделаем то же самое рекуррентно для префикса длины <tex>n-1</tex>. Переместим второй по возрастанию элемент в конец подотрезка, после чего последние два элемента будут отсортированы, и продолжим для префикса длины <tex>n-2</tex>. Таким образом, на каждой итерации мы сделаем две операции, и всего итераций будет не больше <tex>n</tex> (их может быть меньше <tex>n</tex>: если после <tex>i</tex>-ой итерации отсортированным окажется суффикс длины больше, чем <tex>i+1</tex>, можно рекурсивно запустить алгоритм на префиксе длины <tex>n-i-k</tex> вместо <tex>n-i-1</tex>). Тогда суммарное количество операций не превосходит <tex>2n</tex> и любая последовательность может быть отсортирована таким образом. |
== Оценки на количество операций == | == Оценки на количество операций == | ||
Строка 16: | Строка 16: | ||
==== Нижняя ==== | ==== Нижняя ==== | ||
− | Назовём | + | Назовём ''соседством'' в массиве пару элементов, которые идут последовательно в массиве и для которых нет элемента, большего одного из них и меньшего другого. Если максимальный элемент находится в конце массива, это тоже будет считаться соседством (будем считать, что массив сортируется по возрастанию). |
Для любого <tex>n\geqslant 4</tex> существует массив, в котором нет соседств. С другой стороны, отсортированный массив имеет <tex>n</tex> соседств, и за один переворот можно добавить не больше одного соседства, поэтому отсортировать массив, сделав меньше, чем <tex>n</tex> переворотов, невозможно. | Для любого <tex>n\geqslant 4</tex> существует массив, в котором нет соседств. С другой стороны, отсортированный массив имеет <tex>n</tex> соседств, и за один переворот можно добавить не больше одного соседства, поэтому отсортировать массив, сделав меньше, чем <tex>n</tex> переворотов, невозможно. | ||
Строка 23: | Строка 23: | ||
Для начала введём некоторые обозначения. | Для начала введём некоторые обозначения. | ||
− | Пусть <tex>S_n</tex> {{---}} множество перестановок элементов массива длины <tex>n</tex>. Будем считать перестановки строками в <tex>\Sigma^*_n</tex>, где <tex>\Sigma_n=\{1, 2, \ldots, n\}</tex>. Введём бинарное отношение <tex> | + | Пусть <tex>S_n</tex> {{---}} множество перестановок элементов массива длины <tex>n</tex>. Будем считать перестановки строками в <tex>\Sigma^*_n</tex>, где <tex>\Sigma_n=\{1, 2, \ldots, n\}</tex>. Введём бинарное отношение <tex>R: \Sigma^*_n \rightarrow \Sigma^*_n</tex>: <tex>\pi R\sigma</tex> тогда и только тогда, когда <tex>\pi =xy</tex> и <tex>\sigma =x^Ry</tex>, где <tex>\pi, \sigma \in \Sigma^*_n</tex> и <tex>x^R</tex> обозначает развёрнутую <tex>x</tex>. |
− | Пусть <tex>\pi</tex> {{---}} перестановка, тогда <tex>f(\pi)</tex> {{---}} наименьшее <tex>k</tex> такое, что существует последовательность перестановок <tex>\pi_0 | + | Пусть <tex>\pi</tex> {{---}} перестановка, тогда <tex>f(\pi)</tex> {{---}} наименьшее <tex>k</tex> такое, что существует последовательность перестановок <tex>\pi_0 R \pi_1 R \ldots R \pi_k = e_n</tex>, где <tex>e_n = 123\ldots n</tex>. Тогда для числа <tex>n</tex> будем обозначать <tex>f(n)</tex> за максимальное <tex>f(\pi)</tex> среди всех <tex>\pi \in S_n</tex>. |
Пусть <tex>\pi</tex> {{---}} перестановка из <tex>S_n</tex>. Тогда <tex>\pi (j)</tex> {{---}} число номер <tex>j</tex> в перестановке для <tex>1 \leqslant j \leqslant n</tex>. Соседством в <tex>\pi</tex> назовём пару <tex>(j, j+1)</tex> такую, что <tex>|\pi (j) - \pi (j+1)| = 1</tex>. Также будем называть соседством пару <tex>(j, j+1)</tex>, если <tex>\{\pi (j), \pi (j+1) \} = \{1, n\}</tex>. Для <tex>x \in \Sigma^*_n</tex> будем обозначать длину <tex>x</tex> как <tex>|x|</tex>. | Пусть <tex>\pi</tex> {{---}} перестановка из <tex>S_n</tex>. Тогда <tex>\pi (j)</tex> {{---}} число номер <tex>j</tex> в перестановке для <tex>1 \leqslant j \leqslant n</tex>. Соседством в <tex>\pi</tex> назовём пару <tex>(j, j+1)</tex> такую, что <tex>|\pi (j) - \pi (j+1)| = 1</tex>. Также будем называть соседством пару <tex>(j, j+1)</tex>, если <tex>\{\pi (j), \pi (j+1) \} = \{1, n\}</tex>. Для <tex>x \in \Sigma^*_n</tex> будем обозначать длину <tex>x</tex> как <tex>|x|</tex>. | ||
Строка 37: | Строка 37: | ||
{| border="1" style="border-collapse: collapse; float: left; margin-right: 30px;" | {| border="1" style="border-collapse: collapse; float: left; margin-right: 30px;" | ||
− | | colspan="2" style="text-align: center"| a | + | | colspan="2" style="text-align: center"| <tex>a</tex> |
|- | |- | ||
| style="text-align: right" | <tex>k-1 \ldots 1</tex> | | style="text-align: right" | <tex>k-1 \ldots 1</tex> | ||
Строка 56: | Строка 56: | ||
{| border="1" style="border-collapse: collapse;" | {| border="1" style="border-collapse: collapse;" | ||
− | | colspan="2" style="text-align: center" | b | + | | colspan="2" style="text-align: center" | <tex>b</tex> |
|- | |- | ||
| style="text-align: right" | <tex>k\ldots n</tex> | | style="text-align: right" | <tex>k\ldots n</tex> | ||
Строка 71: | Строка 71: | ||
|} | |} | ||
+ | |||
+ | |||
+ | === Алгоритм === | ||
'''Алгоритм''': | '''Алгоритм''': | ||
Строка 306: | Строка 309: | ||
|} | |} | ||
+ | === Корректность алгоритма === | ||
{{Теорема | {{Теорема | ||
− | |statement=Предложенный алгоритм создает перестановку с <tex>n-1</tex> соседством не более чем за <tex>\ | + | |statement=Предложенный алгоритм создает перестановку с <tex>n-1</tex> соседством не более чем за <tex>\dfrac{5n-7}{3}</tex> итераций. |
|proof= | |proof= | ||
Алгоритм всегда завершит работу. На каждой итерации при условии, что в перестановке меньше <tex>n-1</tex> соседств, выполнится одно из условий <tex>1-7</tex>. На каждой итерации создается не меньше одного соседства и ни одного соседства не разрушается, поэтому алгоритм создаст нужную перестановку не больше чем за <tex>n-1</tex> итерацию. | Алгоритм всегда завершит работу. На каждой итерации при условии, что в перестановке меньше <tex>n-1</tex> соседств, выполнится одно из условий <tex>1-7</tex>. На каждой итерации создается не меньше одного соседства и ни одного соседства не разрушается, поэтому алгоритм создаст нужную перестановку не больше чем за <tex>n-1</tex> итерацию. | ||
− | Будем называть случай | + | Будем называть случай 1 ''действием 1'', случай 2 ''действием 2'', случаи 3 и 6 ''действием 3'', случаи 4, 5 и 7 ''действиями'' 4, 5 и 7 соответственно. Пусть <tex>x_i</tex> обозначает количество действий типа <tex>i</tex>, выполненных за время работы алгоритма. Суммарное число разворотов составит |
<tex>z=x_1 + x_2 + 4x_3 + x_4 + 2x_5 + x_7</tex> | <tex>z=x_1 + x_2 + 4x_3 + x_4 + 2x_5 + x_7</tex> | ||
Строка 319: | Строка 323: | ||
Действие 3 может быть разделено на 4 случая. Перед предпоследним разворотом самый левый элемент массива и элемент после <tex>t-o</tex> могут | Действие 3 может быть разделено на 4 случая. Перед предпоследним разворотом самый левый элемент массива и элемент после <tex>t-o</tex> могут | ||
− | # | + | # Быть непарными. |
− | # | + | # Образовывать новый блок. |
− | # | + | # Соединять блок с отдельным элементом. |
− | # | + | # Соединять два блока. |
Эти 4 варианта учитываются, если считать <tex>x_3 = x_{31}+x_{32}+x_{33}+x_{34}</tex>. В таблице 1 записано, как каждое действие увеличивается количество соседств. Суммарное количество соседств можно записать в виде суммы | Эти 4 варианта учитываются, если считать <tex>x_3 = x_{31}+x_{32}+x_{33}+x_{34}</tex>. В таблице 1 записано, как каждое действие увеличивается количество соседств. Суммарное количество соседств можно записать в виде суммы | ||
Строка 349: | Строка 353: | ||
Утверждается, что максимальное значение достигается при | Утверждается, что максимальное значение достигается при | ||
− | <tex>x_1 = \ | + | <tex>x_1 = \dfrac{n+1}{3}</tex>, <tex>x_2 = 0</tex>, <tex>x_3 = x_{31} = \dfrac{n-2}{3}</tex>, <tex>x_4=x_5=x_7=b=0</tex> |
− | В таком случае максимизируемое значение <tex>z=\ | + | В таком случае максимизируемое значение <tex>z=\dfrac{5n-7}{3}</tex>. Для доказательства этого утверждения воспользуемся теоремой о двойственности Данцига-фон Неймана, из которой следует, что максимальное значение равно минимальному значению двойной линейной задачи: |
минимизировать <tex>\omega=\xi_2+(n-1)\xi_3</tex> | минимизировать <tex>\omega=\xi_2+(n-1)\xi_3</tex> | ||
Строка 377: | Строка 381: | ||
<tex>\xi_2+\xi_3 \geqslant 0</tex>. | <tex>\xi_2+\xi_3 \geqslant 0</tex>. | ||
− | Для доказательства утверждения достаточно найти пару <tex>(\xi_2, \xi_3)</tex>, удовлетворяющую этим условиям, при которой <tex>\omega=\xi_2+(n-1)\xi_3=\ | + | Для доказательства утверждения достаточно найти пару <tex>(\xi_2, \xi_3)</tex>, удовлетворяющую этим условиям, при которой <tex>\omega=\xi_2+(n-1)\xi_3=\dfrac{5n-7}{3}</tex>. Такая пара {{---}} <tex>(-\dfrac{2}{3}, \dfrac{5}{3})</tex>. |
− | Граница <tex>\ | + | Граница <tex>\dfrac{5n+5}{3}</tex> получается прибавлением <tex>4</tex> лишних действий, нужных, чтобы добавить последнее соседство. Алгоритм для этого был описан выше. |
Строка 398: | Строка 402: | ||
==== Нижняя ==== | ==== Нижняя ==== | ||
− | Для нижней границы построим последовательность, которая может быть отсортирована не менее чем за <tex>\ | + | Для нижней границы построим последовательность, которая может быть отсортирована не менее чем за <tex>\dfrac{17n}{16}</tex> разворотов. |
Пусть <tex>\tau = 17536428</tex>. Для положительного целого <tex>k</tex> будем обозначать <tex>\tau</tex>, в которой каждое число увеличено на <tex>8(k-1)</tex>, как <tex>\tau_k</tex>. Другими словами, <tex>\tau_k = 1_k 7_k 5_k 3_k 6_k 4_k 2_k 8_k</tex>, где <tex>m_k = m+8(k-1)</tex>. Пусть перестановка <tex>\chi = \tau_1 \tau_2^R \tau_3 \tau_4^R \ldots \tau_{m-1} \tau_m^R</tex>, где <tex>m</tex> {{---}} чётное целое число, и пусть <tex>n=|\chi |=8m</tex>. | Пусть <tex>\tau = 17536428</tex>. Для положительного целого <tex>k</tex> будем обозначать <tex>\tau</tex>, в которой каждое число увеличено на <tex>8(k-1)</tex>, как <tex>\tau_k</tex>. Другими словами, <tex>\tau_k = 1_k 7_k 5_k 3_k 6_k 4_k 2_k 8_k</tex>, где <tex>m_k = m+8(k-1)</tex>. Пусть перестановка <tex>\chi = \tau_1 \tau_2^R \tau_3 \tau_4^R \ldots \tau_{m-1} \tau_m^R</tex>, где <tex>m</tex> {{---}} чётное целое число, и пусть <tex>n=|\chi |=8m</tex>. | ||
{{Теорема | {{Теорема | ||
− | |statement= | + | |statement=<tex>f(\chi ) \geqslant \dfrac{17n}{16}</tex> |
}} | }} | ||
Строка 414: | Строка 418: | ||
== См. также == | == См. также == | ||
− | * [[ | + | * [[Timsort | Timsort]] |
+ | * [[Быстрая сортировка | Быстрая сортировка]] | ||
== Источники информации == | == Источники информации == | ||
Строка 421: | Строка 426: | ||
*[http://www.eecs.berkeley.edu/~christos/papers/GP79.pdf William H. Gates; Christos H. Papadimitriou Bounds for sorting by prefix reversal] | *[http://www.eecs.berkeley.edu/~christos/papers/GP79.pdf William H. Gates; Christos H. Papadimitriou Bounds for sorting by prefix reversal] | ||
− | [[Категория: | + | [[Категория: Сортировки]] |
Версия 21:04, 20 января 2016
Блинная сортировка (англ. pancake sorting) — алгоритм сортировки с помощью одной операции — переворота элементов последовательности до какого-то индекса. Разумеется, разрешены сравнения, при оценке времени работы этого алгоритма оценивается количество переворотов, а не сравнений. Название алгоритма пошло от изначальной задачи отсортировать стопку блинов по возрастанию размера.
Содержание
Корректность
Для начала покажем, что любую последовательность можно отсортировать с помощью блинной сортировки. Для этого будет предложен алгоритм, позволяющий отсортировать любой массив, сделав не более
операций, где — размер массива.Найдём максимальный элемент последовательности с номером
и развернём префикс массива до -ого элемента. Теперь максимальный элемент находится в начале массива. Развернём весь массив, теперь максимальный элемент находится в конце массива. Сделаем то же самое рекуррентно для префикса длины . Переместим второй по возрастанию элемент в конец подотрезка, после чего последние два элемента будут отсортированы, и продолжим для префикса длины . Таким образом, на каждой итерации мы сделаем две операции, и всего итераций будет не больше (их может быть меньше : если после -ой итерации отсортированным окажется суффикс длины больше, чем , можно рекурсивно запустить алгоритм на префиксе длины вместо ). Тогда суммарное количество операций не превосходит и любая последовательность может быть отсортирована таким образом.Оценки на количество операций
Существуют простые оценки:
сверху и, для , снизу. Более сложные границы были предложены в 1978 году Биллом Гейтсом и Христосом Пападимитриу, и улучшить их получилось лишь в 2008.Наивные
Верхняя
Оценка в
операций следует из доказательства корректности алгоритма, в котором предлагается алгоритм сортировки любой последовательности за операций. Она может быть улучшена до чуть более умной сортировкой последних элементов.Нижняя
Назовём соседством в массиве пару элементов, которые идут последовательно в массиве и для которых нет элемента, большего одного из них и меньшего другого. Если максимальный элемент находится в конце массива, это тоже будет считаться соседством (будем считать, что массив сортируется по возрастанию).
Для любого
существует массив, в котором нет соседств. С другой стороны, отсортированный массив имеет соседств, и за один переворот можно добавить не больше одного соседства, поэтому отсортировать массив, сделав меньше, чем переворотов, невозможно.Продвинутые
Для начала введём некоторые обозначения.
Пусть
— множество перестановок элементов массива длины . Будем считать перестановки строками в , где . Введём бинарное отношение : тогда и только тогда, когда и , где и обозначает развёрнутую .Пусть
— перестановка, тогда — наименьшее такое, что существует последовательность перестановок , где . Тогда для числа будем обозначать за максимальное среди всех .Пусть
— перестановка из . Тогда — число номер в перестановке для . Соседством в назовём пару такую, что . Также будем называть соседством пару , если . Для будем обозначать длину как .Пусть
, . будем называть блоком, если для любого такого, что , пара — соседство, при этом пары и не являются соседствами. Если не является частью блока, то есть и — не соседства, элемент будем называть свободным.За
будем обозначать элемент из . Подразумевается, что сложение проводится по модулю .Верхняя
Будет предложен алгоритм, который изменит перестановку
так, чтобы в ней было соседство. После этого отсортировать массив можно не более чем за 4 действия (в иллюстрациях дальше показана последовательность действий, состояние в следующей строке получается из состояния в предыдущей одним разворотом префикса):
Алгоритм
Алгоритм:
- входные данные: перестановка
- выходные данные: перестановка с соседством
Циклически повторять следующее. Пусть
— первый элемент ( ). Как минимум одно из условий выполняется, выполнить соответствующее действие:- свободный, свободный. Выполнить разворот ,
- свободный, — первый элемент блока. Выполнить разворот ,
- свободный, и , и — последние элементы в блоке. Выполнить развороты ,
- в блоке, свободен. Выполнить разворот ,
- в блоке, — первый элемент блока. Выполнить разворот ,
- в блоке с последним элементом ( ), — последний элемент другого блока, и свободен. Выполнить перевороты или в зависимости от расположения блоков,
- в блоке с последним элементом ( ), — последний элемент другого блока, и в блоке. Выполнить развороты или в зависимости от того, в начале или в конце блока находится элемент ,
- ничего из перечисленного выше. В перестановке соседство. Завершить работу алгоритма.
Необходимые развороты:
Корректность алгоритма
Теорема: |
Предложенный алгоритм создает перестановку с соседством не более чем за итераций. |
Доказательство: |
Алгоритм всегда завершит работу. На каждой итерации при условии, что в перестановке меньше соседств, выполнится одно из условий . На каждой итерации создается не меньше одного соседства и ни одного соседства не разрушается, поэтому алгоритм создаст нужную перестановку не больше чем за итерацию.Будем называть случай 1 действием 1, случай 2 действием 2, случаи 3 и 6 действием 3, случаи 4, 5 и 7 действиями 4, 5 и 7 соответственно. Пусть обозначает количество действий типа , выполненных за время работы алгоритма. Суммарное число разворотов составит
умножено на количество разворотов, выполняемых за это действие. Действие 3 может быть разделено на 4 случая. Перед предпоследним разворотом самый левый элемент массива и элемент после могут
Эти 4 варианта учитываются, если считать . В таблице 1 записано, как каждое действие увеличивается количество соседств. Суммарное количество соседств можно записать в виде суммы
Если — количество блоков в изначальной перестановке, то, поскольку каждое действие изменяет количество блоков так, как показано в таблице 1, а в конечной перестановке 1 блок, имеем
Поскольку , из первого равенства следует
Таким образом, для нахождения худшего случая нужно максимизировать
так, чтобы выполнялось равенство
и неравенство
Утверждается, что максимальное значение достигается при , , , В таком случае максимизируемое значение . Для доказательства этого утверждения воспользуемся теоремой о двойственности Данцига-фон Неймана, из которой следует, что максимальное значение равно минимальному значению двойной линейной задачи:минимизировать при условиях , , , , , , , , , . Для доказательства утверждения достаточно найти пару Граница , удовлетворяющую этим условиям, при которой . Такая пара — . получается прибавлением лишних действий, нужных, чтобы добавить последнее соседство. Алгоритм для этого был описан выше. |
Таблица 1 | |||||||||
Действие | |||||||||
Количество разворотов | |||||||||
Увеличение количества соседств | |||||||||
Изменение количества блоков |
Нижняя
Для нижней границы построим последовательность, которая может быть отсортирована не менее чем за
разворотов.Пусть
. Для положительного целого будем обозначать , в которой каждое число увеличено на , как . Другими словами, , где . Пусть перестановка , где — чётное целое число, и пусть .Теорема: |
Задача о подгоревших блинах
Изначально задача по подгоревших блинах (англ. burnt pancake problem) формулировалась так:
Каждый блин в стопке подгорел с одной стороны. Требуется отсортировать блины по возрастанию (убыванию) диаметра так, чтобы они все лежали на тарелке подгоревшей стороной вниз.
Другими словами, нужно предложить алгоритм блинной сортировки, в котором каждый элемент будет развёрнут чётное число раз.