Персистентный стек — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
Строка 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>
<br>
+
Аналогично выполним <tex>push(2, 10)</tex> и <tex>push(1, 6)</tex>:
Аналогично выполним push(2, 10) и push(1, 6):
 
 
<br><br>
 
<br><br>
 
[[Файл:2beb71892fd79b675e095d5432827d03.jpg|nothumb]]
 
[[Файл:2beb71892fd79b675e095d5432827d03.jpg|nothumb]]
 
<br>
 
<br>
  
<br><br>
+
Очевидно, что все 4 стека сейчас верно построены и легко восстанавливаются. Давайте теперь попробуем выполнить последовательно операции <tex>pop(2)</tex> и <tex>pop(3)</tex>:
 
 
<br><br>
 
Очевидно, что все 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>
  
<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><br><br>
+
<br>
  
 +
В итоге мы имеем доступ ко всем версиям стека за <tex>O(1)</tex> времени и <tex>O(n)</tex> памяти.
  
 
== См. также==
 
== См. также==

Версия 21:31, 29 февраля 2012

Определение:
Персистентными структурами данных мы будем называть такие структуры, что при всяком их изменении остается доступ ко всем предыдущим версиям этой структуры.


Рассмотрим такую структуру на примере стека.


Наивная реализация

Самое простое и очевидное решение этой задачи — симуляция описанного процесса, т.е. честное копирование стека при каждой операции.
Очевидно, что это не самое эффективное решение. Сложность одной операции составляет [math]O(n)[/math] и количество требуемой памяти — [math]O(n * n)[/math].

Нормальная реализация

Попробуем решить задачу эффективнее. Вместо n копий стека будем хранить n первых элементов. Тогда операции push и pop будут иметь следующий вид:

  • [math]push(x, i)[/math] - создает новый элемент со значением x, который ссылается на элемент с номером i как на предыдущий элемент в стеке.
  • [math]pop(i)[/math] - возвращает значение, хранящееся в элементе с номером i и копирует элемент, предыдущий для него.

Результирующие стеки будут иметь номер n + 1.

Пример

Пусть изначально у нас есть один пустой стек. Для удобства, будем хранить его как «голову» с пометкой пустого стека:
nothumb


Далее выполним [math]push(1, 5)[/math]. Создается новая вершина со значением 5, ссылающаяся на 1-ую:
nothumb

Аналогично выполним [math]push(2, 10)[/math] и [math]push(1, 6)[/math]:

nothumb

Очевидно, что все 4 стека сейчас верно построены и легко восстанавливаются. Давайте теперь попробуем выполнить последовательно операции [math]pop(2)[/math] и [math]pop(3)[/math]:


  • [math]pop(2)[/math] возвращает 5 и копирует 1-ую вершину. Результирующий пятый стек — пустой.


nothumb



  • [math]pop(3)[/math] возвращает 10 и копирует 2-ую вершину: получаем шестой стек.



nothumb

В итоге мы имеем доступ ко всем версиям стека за [math]O(1)[/math] времени и [math]O(n)[/math] памяти.

См. также

Ссылки