Персистентная очередь — различия между версиями
Genyaz (обсуждение | вклад) |
Genyaz (обсуждение | вклад) |
||
| Строка 15: | Строка 15: | ||
Режим перекопирования активируется, когда в стеке <tex>L</tex> становится больше элементов, чем в стеке <tex>R</tex>. Пусть в стеке <tex>R</tex> в этот момент находилось <tex>n</tex> элементов, тогда в стеке <tex>L</tex> находилось <tex>n+1</tex> элементов. Заметим, что мы можем корректно обработать только <tex>n</tex> запросов <tex>pop</tex>, операции <tex>push</tex> и <tex>empty</tex> мы обрабатываем корректно всегда, следовательно мы должны закончить перекопирование за <tex>n+1</tex> операцию, включая активирующую. | Режим перекопирования активируется, когда в стеке <tex>L</tex> становится больше элементов, чем в стеке <tex>R</tex>. Пусть в стеке <tex>R</tex> в этот момент находилось <tex>n</tex> элементов, тогда в стеке <tex>L</tex> находилось <tex>n+1</tex> элементов. Заметим, что мы можем корректно обработать только <tex>n</tex> запросов <tex>pop</tex>, операции <tex>push</tex> и <tex>empty</tex> мы обрабатываем корректно всегда, следовательно мы должны закончить перекопирование за <tex>n+1</tex> операцию, включая активирующую. | ||
| − | Для | + | Для завершения перекопирования нужно: |
# Переместить все содержимое стека <tex>R</tex> в <tex>T</tex>, <tex>n</tex> операций. | # Переместить все содержимое стека <tex>R</tex> в <tex>T</tex>, <tex>n</tex> операций. | ||
# Переместить все содержимое стека <tex>L</tex> в <tex>R</tex>, <tex>n + 1</tex> операция. | # Переместить все содержимое стека <tex>L</tex> в <tex>R</tex>, <tex>n + 1</tex> операция. | ||
| Строка 22: | Строка 22: | ||
Итого, мы должны сделать <tex>3 \cdot n + 3</tex> дополнительных действия за <tex>n + 1</tex> операций, то есть выполняя <tex>O(1)=3</tex> дополнительных действия на операцию, мы сможем завершить перекопирование и вернуться в обычный режим до исчерпания стека <tex>R'</tex>, получив <tex>O(1)</tex> реального времени и <tex>O(1)</tex> памяти на персистентность на операцию. | Итого, мы должны сделать <tex>3 \cdot n + 3</tex> дополнительных действия за <tex>n + 1</tex> операций, то есть выполняя <tex>O(1)=3</tex> дополнительных действия на операцию, мы сможем завершить перекопирование и вернуться в обычный режим до исчерпания стека <tex>R'</tex>, получив <tex>O(1)</tex> реального времени и <tex>O(1)</tex> памяти на персистентность на операцию. | ||
| + | |||
| + | Теперь рассмотрим, какие изменения произошли за время перекопирования. Пусть среди <tex>n</tex> следующих за активацией операций у нас <tex>x</tex> операций <tex>pop</tex> и <tex>n-x</tex> операций <tex>push</tex>. Тогда в стеке <tex>R</tex> оказалось <tex>2 \cdot n + 1 - x</tex> элементов, а в новом стеке <tex>L</tex> оказалось <tex>n - x</tex> элементов. Тогда в стеке <tex>R</tex> на <tex>n+1</tex> больше элементов, чем в стеке <tex>L</tex>, а это значит, что до следующего режима перекопирования <tex>n + 2</tex> операции, и за это время мы успеем очистить старый стек <tex>Rc</tex>, в котором находится максимум <tex>n</tex> ненужных элементов, просто удаляя при каждой операции в обычном режиме один элемент из <tex>Rc</tex>, если он не пустой. | ||
| + | |||
| + | Заметим, что вышеприведенный алгоритм гарантирует нам, что в обычном режиме в стеке <tex>L</tex> находится не больше элементов, чем в <tex>R</tex>, так что проверка на пустоту очереди при обычном режиме сводится к проверке на пустоту стека <tex>R</tex>. | ||
| + | |||
[[Категория: Дискретная математика и алгоритмы]] | [[Категория: Дискретная математика и алгоритмы]] | ||
[[Категория: Амортизационный анализ]] | [[Категория: Амортизационный анализ]] | ||
Версия 11:17, 7 июня 2013
После того, как мы получили очередь в реальном времени с обычными стеками, ее можно легко превратить в персистентную, сделав все стеки персистентными, но реально можно ограничиться всего пятью персистентными стеками.
Эффективная реализация
По сравнению с реализацией на шести стеках, теперь у нас все стеки персистентные, а значит у нас нет необходимости хранить отдельно копию стека , так как все его версии теперь доступны по его персистентности. Это позволяет нам заменить два стека на один стек , в который мы и будем записывать перекопированный кусок.
Персистентная очередь будет состоять из пяти персистентных стеков: , причем стеки используются для операций , стеки используются для операций , а стек используется для временного хранения содержимого стека .
В каждый момент времени определено, какой стек из стеков сейчас используется для операций , какой стек из стеков сейчас используется для операций , а также находится ли очередь в режиме перекопирования (recopy mode).
В режиме перекопирования операции перенаправляются в парный стек ; операции выполняются над последней персистентной версией , тогда операция всегда возвращает , так как стек содержит элементов, а в режиме перекопирования мы не можем извлечь их операцией .
Для хранения последней персистентной версии мы используем второй имеющийся стек , а также переменную — количество элементов, оставшихся в , оно уменьшается на с каждой следующей операцией .
Режим перекопирования активируется, когда в стеке становится больше элементов, чем в стеке . Пусть в стеке в этот момент находилось элементов, тогда в стеке находилось элементов. Заметим, что мы можем корректно обработать только запросов , операции и мы обрабатываем корректно всегда, следовательно мы должны закончить перекопирование за операцию, включая активирующую.
Для завершения перекопирования нужно:
- Переместить все содержимое стека в , операций.
- Переместить все содержимое стека в , операция.
- Переместить первые элементов стека в , а оставшиеся элементы выкинуть, операций.
- Обменять местами стеки и , операции.
Итого, мы должны сделать дополнительных действия за операций, то есть выполняя дополнительных действия на операцию, мы сможем завершить перекопирование и вернуться в обычный режим до исчерпания стека , получив реального времени и памяти на персистентность на операцию.
Теперь рассмотрим, какие изменения произошли за время перекопирования. Пусть среди следующих за активацией операций у нас операций и операций . Тогда в стеке оказалось элементов, а в новом стеке оказалось элементов. Тогда в стеке на больше элементов, чем в стеке , а это значит, что до следующего режима перекопирования операции, и за это время мы успеем очистить старый стек , в котором находится максимум ненужных элементов, просто удаляя при каждой операции в обычном режиме один элемент из , если он не пустой.
Заметим, что вышеприведенный алгоритм гарантирует нам, что в обычном режиме в стеке находится не больше элементов, чем в , так что проверка на пустоту очереди при обычном режиме сводится к проверке на пустоту стека .