1632
правки
Изменения
м
List <Stackfont color = green>// Получение отсортированного массива<E>/font> piles '''forbool''' comparePiles(i = 0Stack<E> x, Stack<E> y): return x.peek() < y.n-1peek() E[] getSortedArray(E[] source): List<Stack<E> pile > piles = PilecreatePiles(source[i]): i = BinarySearch PriorityQueue<Stack<E>> q(piles, pile) '''ifcomparator''' (i==piles.sizecomparePiles) piles.Add(pile) '''elsefor'''i = 0..n - 1 piles answer[i]= q.Addmin(Pile).pop(source[i])) piles[piles.size-1].Top.Previous = piles[piles.size-2].Top // для последующего получения НВП '''return''' answer
bool comparePiles (Stack== Пример ==Рассмотрим работу алгоритма на массиве <Etex> x[3, 1, 2, 4, 5, Stack0]<E/tex> y) return x.Peek()<y.Peek() PriorityQueue<Stack<E>> q(piles, comparePiles)
'''forФормирование стопок:'''(i=0..n-1) answer[i]=q.Min().Pop()
//Получение наибольшей возрастающей подпоследовательности{| style="background-color:#CCC;margin:0.5px"!style="background-color:#EEE"| Стопка 1!style="background-color:#EEE"| Стопка 2!style="background-color:#EEE"| Стопка 3!style="background-color:#EEE"| Стопка 4!style="background-color:#EEE"| Стопка 5!style="background-color:#EEE"| Стопка 6|-|style="background-color:#FFF;padding:2px 10px"| 3|style="background-color:#FFF;padding:2px 10px"| не существует|style="background-color:#FFF;padding:2px 10px"| не существует|style="background-color:#FFF;padding:2px 10px"| не существует|style="background-color:#FFF;padding:2px 10px"| не существует|style="background-color:#FFF;padding:2px 10px"| не существует|-|style="background-color:#FFF;padding:2px 10px"| 3 1|style="background-color:#FFF;padding:2px 10px"| не существует|style="background-color:#FFF;padding:2px 10px"| не существует|style="background-color:#FFF;padding:2px 10px"| не существует|style="background-color:#FFF;padding:2px 10px"| не существует|style="background-color:#FFF;padding:2px 10px"| не существует|-|style="background-color:#FFF;padding:2px 10px"| 3 1|style="background-color:#FFF;padding:2px 10px"| 2 (предшествующий элемент - 1)|style="background-color:#FFF;padding:2px 10px"| не существует|style="background-color:#FFF;padding:2px 10px"| не существует|style="background-color:#FFF;padding:2px 10px"| не существует|style="background-color:#FFF;padding:2px 10px"| не существует|-|style="background-color:#FFF;padding:2px 10px"| 3 1|style="background-color:#FFF;padding:2px 10px"| 2|style="background-color:#FFF;padding:2px 10px"| 4 (предшествующий элемент - 2)|style="background-color:#FFF;padding:2px 10px"| не существует|style="background-color:#FFF;padding:2px 10px"| не существует|style="background-color:#FFF;padding:2px 10px"| не существует|-|style="background-color:#FFF;padding:2px 10px"| 3 1|style="background-color:#FFF;padding:2px 10px"| 2|style="background-color:#FFF;padding:2px 10px"| 4|style="background-color:#FFF;padding:2px 10px"| 5 (предшествующий элемент - 4)|style="background-color:#FFF;padding:2px 10px"| не существует|style="background-color:#FFF;padding:2px 10px"| не существует|-|style="background-color:#FFF;padding:2px 10px"| 3 1 0|style="background-color:#FFF;padding:2px 10px"| 2|style="background-color:#FFF;padding:2px 10px"| 4|style="background-color:#FFF;padding:2px 10px"| 5|style="background-color:#FFF;padding:2px 10px"| не существует|style="background-color:#FFF;padding:2px 10px"| не существует|}
answer[n'''Получим отсортированный массив:'''{| style="background-color:#CCC;margin:0.5px"!style="background-color:#EEE"| Вершины!style="background-color:#EEE"| Минимум|-|style="background-color:#FFF;padding:2px 10px"| 0 2 4 5|style="background-color:#FFF;padding:2px 10px"| 0|-|style="background-color:#FFF;padding:2px 10px"| 1]2 4 5|style=piles[piles.size"background-color:#FFF;padding:2px 10px"| 1].Top E prev |-|style= answer[n"background-1].Previouscolor:#FFF;padding:2px 10px"| 3 2 4 5 '''for'''(i|style=n"background-color:#FFF;padding:2px 10px"| 2..0) answer[i]|-|style="background-color:#FFF;padding:2px 10px"| 3 4 5|style="background-color:#FFF;padding:2px 10px"| 3|-|style="background-color:#FFF;padding:2px 10px"| 4 5|style="background-color:#FFF;padding:2px 10px"| 4|-|style=prev"background-color:#FFF;padding:2px 10px"| 5 prev |style= answer[i].Previous"background-color:#FFF;padding:2px 10px"| 5|}
== Литература ==
rollbackEdits.php mass rollback
'''Терпеливая сортировка '''(англ. '''patience sorting''') {{- --}} алгоритм сортировки с худшей сложностью <tex>O(n</tex> <tex>\log</tex> <tex>n)</tex>. Позволяет также вычислить длину [[Задача о наибольшей возрастающей подпоследовательности|наибольшей возрастающей подпоследовательности ]] данного массива. Алгоритм назван по одному из названий карточной игры "Солитёр" — {{---}} "Patience".
== Алгоритм ==
Имеем массив <tex>source [0..n-1]</tex>, элементы которого нужно отсортировать по возрастанию. Разложим элементы массива по стопкам: для того чтобы положить элемент в стопку, требуется выполнение условия — {{---}} новый элемент меньше элемента, лежащего на вершине стопки; либо создадим новую стопку справа от уже имеющихся и сделаем наш элемент её вершиной наш элемент. Используем жадную стратегию: каждый элемент кладётся в самую левую стопку из возможных, если же таковой нет, справа от существующих стопок создаётся новая.Для получения отсортированного массива сначала построим массив стопок, затем выполним <tex>n</tex> шагов(здесь и далее нумерация шагов начинается с единицы): на <tex>i</tex>-м шаге выберем из всех вершин стопок наименьшую, извлечём её и запишем в массив <tex>ans [0..n-1]</tex> на <tex>i-1</tex>-ю позицию.Длина Мы формируем новую стопку, когда встречаем элемент больший, чем вершины всех стопок, расположенных слева. В то же время стопки слева были созданы ранее, то есть элементы в них идут в исходной последовательности раньше текущего. Каждая стопка представляет собой убывающую последовательность, то есть длина НВП в пределах стопки равна единице, поэтому появление новой стопки можно понимать как увеличение длины наибольшей возрастающей подпоследовательности на единицу (изначально длина НВП равна единице). Поэтому длина наибольшей возрастающей подпоследовательности равна количеству стопок. Для получения наибольшей возрастающей подпоследовательности при формировании стопок проведём следующие операции: каждый раз, положив элемент на вершину стопки, будем создавать указатель на возможный предыдущий элемент (вершину ближайшей слева стопки). В конце для получения наибольшей возрастающей подпоследовательности нужно выполнить <tex>p</tex> шагов, начав с вершины самой правой стопки: на <tex>i</tex>-м шаге записать в <tex>lis[0..p-1]</tex>на <tex>(p-i)</tex>-ю позицию текущий элемент, перейти к предыдущему элементу по указателю,где <tex>p</tex> — {{---}} количество стопок. == Сложность ==Создадим [[список|список]] [[стек|стеков]] для хранения стопок. При раскладывании элементов по стопкам для поиска самой левой подходящей стопки используем [[Целочисленный двоичный поиск|бинарный поиск]]. Соответственно, на поиск самой левой стопки занимает <tex>O(\log</tex> <tex>p)</tex>, где p{{-i--}} количество стопок (стеков). Таким образом, временная сложность раскладывания по стопкам не превышает <tex>O(n \log n)</tex>. Для получения отстортированного массива используем [[Двоичная куча|бинарную кучу]]. На каждом шаге алгоритма необходимо извлечь из кучи стек с минимальной вершиной за <tex>O(\log</tex> <tex>p)</tex>, где <tex>p</tex>{{-ю позицию текущий элемент--}} количество стеков в куче. Снять вершину выбранного стека и вернуть его в кучу за <tex>O(\log</tex> <tex>p)</tex>. Получение отсортированного массива займёт <tex>O(n \log</tex> <tex>n)</tex> времени.Получение наибольшей возрастающей подпоследовательности выполняется за <tex>O(n)</tex> по описанному выше алгоритму.Таким образом, перейти к предыдущему элементу по указателюалгоритм сортировки требует <tex>O(n \log n)</tex> времени в худшем случае и <tex>O(n)</tex> дополнительной памяти при любом раскладе.
== Псевдокод ==
Map<E, E> previous <font color = green>//формирование стопок</font> List<Stack<E>> createPiles(E[] source): List<Stack<E>> piles '''for''' i = 0..n - 1 Stack<E> pile = Pile(source[i]) j = binarySearch(piles, pile) '''if''' j == piles.size piles.add(pile) '''else''' piles[j].add(Pile(source[i])) previous.set(piles[j].peek(), piles[j - 1].peek()) <font color=green> // для последующего получения НВП </font> '''return''' piles
<font color = green>//Получение отсортированного массиванаибольшей возрастающей подпоследовательности</font> E[] getLIS(List<Stack<E>> piles): lis[n - 1] = piles[piles.size - 1].peek() E prev = previous.get(lis[n - 1]) '''for''' i = n - 2..0 lis[i] = prev prev = previous.get(lis[i]) '''return''' lis
'''Получим наибольшую возрастающую подпоследовательность:'''{| style="background-color:#CCC;margin:0.5px"!style="background-color:#EEE"| Текущий элемент!style="background-color:#EEE"| Предшествующий элемент|-|style="background-color:#FFF;padding:2px 10px"| 5|style="background-color:#FFF;padding:2px 10px"| 4|-|style="background-color:#FFF;padding:2px 10px"| 4|style= Пример "background-color:#FFF;padding:2px 10px"| 2|-|style="background-color:#FFF;padding:2px 10px"| 2|style="background-color:#FFF;padding:2px 10px"| 1|-|style="background-color:#FFF;padding:2px 10px"| 1|style="background-color:#FFF;padding:2px 10px"| nullтест|}
== Ссылки Источники информации ==*[http[wikipedia://en.wikipedia.org/wiki/Patience_sorting Терпеливая сортировка в английской ВикипедииPatience sorting | Wikipedia {{---}} Patience sorting ]]
*[http://www.cs.princeton.edu/courses/archive/spring13/cos423/lectures/LongestIncreasingSubsequence.pdf Наглядное описание алгоритма на английском языке]
*''Sergei Bespamyatnikh and Michael Segal'' Pacific Inst. for the Math. Sci. Preprints, PIMS-99-3., pp.7–8
[[Категория: Дискретная математика и алгоритмы]]
[[Категория: Сортировки]]