Персистентный стек — различия между версиями
Yurik (обсуждение | вклад) |
Yurik (обсуждение | вклад) |
||
Строка 1: | Строка 1: | ||
− | |||
{{Определение | {{Определение | ||
|definition=Персистентными структурами данных мы будем называть такие структуры, что при всяком их изменении остается доступ ко всем предыдущим версиям этой структуры. | |definition=Персистентными структурами данных мы будем называть такие структуры, что при всяком их изменении остается доступ ко всем предыдущим версиям этой структуры. | ||
Строка 17: | Строка 16: | ||
* <tex>push(x, i)</tex> - создает новый элемент со значением x, который ссылается на элемент с номером i как на предыдущий элемент в стеке. | * <tex>push(x, i)</tex> - создает новый элемент со значением x, который ссылается на элемент с номером i как на предыдущий элемент в стеке. | ||
* <tex>pop(i)</tex> - возвращает значение, хранящееся в элементе с номером i и копирует элемент, предыдущий для него. | * <tex>pop(i)</tex> - возвращает значение, хранящееся в элементе с номером i и копирует элемент, предыдущий для него. | ||
+ | Результирующие стеки будут иметь номер n + 1. | ||
− | Пример | + | == Пример == |
Пусть изначально у нас есть один пустой стек. Для удобства, будем хранить его как «голову» с пометкой пустого стека: | Пусть изначально у нас есть один пустой стек. Для удобства, будем хранить его как «голову» с пометкой пустого стека: | ||
Строка 25: | Строка 25: | ||
<br> | <br> | ||
<br> | <br> | ||
− | Далее выполним push(1, 5). Создается новая вершина со значением 5, ссылающаяся на 1-ую: | + | Далее выполним <tex>push(1, 5)</tex>. Создается новая вершина со значением 5, ссылающаяся на 1-ую: |
+ | <br> | ||
[[Файл:612b6fe1562242b3a455b2abb698dfc9.jpg|nothumb]]<br> | [[Файл:612b6fe1562242b3a455b2abb698dfc9.jpg|nothumb]]<br> | ||
<br> | <br> | ||
− | < | + | Аналогично выполним <tex>push(2, 10)</tex> и <tex>push(1, 6)</tex>: |
− | |||
<br><br> | <br><br> | ||
[[Файл:2beb71892fd79b675e095d5432827d03.jpg|nothumb]] | [[Файл:2beb71892fd79b675e095d5432827d03.jpg|nothumb]] | ||
<br> | <br> | ||
− | + | Очевидно, что все 4 стека сейчас верно построены и легко восстанавливаются. Давайте теперь попробуем выполнить последовательно операции <tex>pop(2)</tex> и <tex>pop(3)</tex>: | |
− | |||
− | |||
− | Очевидно, что все 4 стека сейчас верно построены и легко восстанавливаются. Давайте теперь попробуем выполнить последовательно операции pop(2) и pop(3): | ||
<br> | <br> | ||
− | pop(2) возвращает 5 и копирует 1-ую вершину. Результирующий пятый стек — пустой. | + | * <tex>pop(2)</tex> возвращает 5 и копирует 1-ую вершину. Результирующий пятый стек — пустой. |
<br> | <br> | ||
[[Файл:3ab7456751529d76c5f1392d5d3b5fcb.jpg|nothumb]] | [[Файл:3ab7456751529d76c5f1392d5d3b5fcb.jpg|nothumb]] | ||
Строка 46: | Строка 43: | ||
<br><br> | <br><br> | ||
− | < | + | * <tex>pop(3)</tex> возвращает 10 и копирует 2-ую вершину: получаем шестой стек. |
− | |||
− | pop(3) возвращает 10 и копирует 2-ую вершину: получаем шестой стек. | ||
<br><br> | <br><br> | ||
[[Файл:Eced2ebbcee643d6c87576b0d3460785.jpg|nothumb]]<br> | [[Файл:Eced2ebbcee643d6c87576b0d3460785.jpg|nothumb]]<br> | ||
− | + | <br> | |
+ | В итоге мы имеем доступ ко всем версиям стека за <tex>O(1)</tex> времени и <tex>O(n)</tex> памяти. | ||
== См. также== | == См. также== |
Версия 21:31, 29 февраля 2012
Определение: |
Персистентными структурами данных мы будем называть такие структуры, что при всяком их изменении остается доступ ко всем предыдущим версиям этой структуры. |
Рассмотрим такую структуру на примере стека.
Наивная реализация
Самое простое и очевидное решение этой задачи — симуляция описанного процесса, т.е. честное копирование стека при каждой операции.
Очевидно, что это не самое эффективное решение. Сложность одной операции составляет и количество требуемой памяти — .
Нормальная реализация
Попробуем решить задачу эффективнее. Вместо n копий стека будем хранить n первых элементов. Тогда операции push и pop будут иметь следующий вид:
- - создает новый элемент со значением x, который ссылается на элемент с номером i как на предыдущий элемент в стеке.
- - возвращает значение, хранящееся в элементе с номером i и копирует элемент, предыдущий для него.
Результирующие стеки будут иметь номер n + 1.
Пример
Пусть изначально у нас есть один пустой стек. Для удобства, будем хранить его как «голову» с пометкой пустого стека:
Далее выполним . Создается новая вершина со значением 5, ссылающаяся на 1-ую:
Аналогично выполним и :
Очевидно, что все 4 стека сейчас верно построены и легко восстанавливаются. Давайте теперь попробуем выполнить последовательно операции
и :
- возвращает 5 и копирует 1-ую вершину. Результирующий пятый стек — пустой.
- возвращает 10 и копирует 2-ую вершину: получаем шестой стек.
В итоге мы имеем доступ ко всем версиям стека за
времени и памяти.