Изменения

Перейти к: навигация, поиск

Персистентный стек

77 байт убрано, 16:34, 7 июня 2012
Нет описания правки
Самое простое и очевидное решение этой задачи — честное копирование стека при каждой операции. <br>
Очевидно, что это не самое эффективное решение. Сложность одной операции составляет <tex>O(n)</tex> и количество требуемой памяти — <tex>O(n^2)</tex>.
== Эффективная реализация ==
 Попробуем решить задачу эффективнее. Заведем массив запросов, модифицирующих стек. <br>У каждого элемента массива будет 2 поля: значение в вершине стека и индекс предыдущей версии стека.<br>
Тогда операции push и pop будут иметь следующий вид:<br>
* <tex>push(i, x)</tex> — добавляет элемент х к стеку в стек с номером i, результирующий стек будет иметь номер <tex> n + 1</tex>.
* <tex>pop(i)</tex> — возвращает значение, хранящееся в элементе с номером i и копирует элемент, предыдущий для него.
результирующий стек будет иметь номер <tex> n + 1</tex>.
== Пример ==
* Пусть изначально у нас есть один пустой стек. Запишем его в массив.<br>
{| border = 1; cellspacing = 0; class="wikitable"
|- align = "center"
!index
|!1
|-align = "center"
!value
|}
<br><br>* Далее выполним <tex>push(1, 3)</tex>. Создается новая вершина со значением 3, ссылающаяся на 1-ую, помещаем ее во 2-ую ячейку массива:<br>
{| border = 1; cellspacing = 0; class="wikitable"
|- align = "center"
!index
|!1|!&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;
|-align = "center"
!value
|}
<br>* Аналогично выполним <tex>push(2, 5)</tex>:<br>
{| border = 1; cellspacing = 0; class="wikitable"
|- align = "center"
!index
|!1|!&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;|!&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;
|-align = "center"
!value
|}
<br>
<br>
<br>* Выполним <tex>pop(3)</tex>. он возвращает 5 и копирует 2-ую вершину.<br>
{| border = 1; cellspacing = 0; class="wikitable"
|- align = "center"
!index
|!1|!&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;|!&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;|!&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;
|-align = "center"
!value
|}
<br><br>
* Так будет выглядеть массив после последовательности операций <tex>push(3, 6), push(5, 1), pop(4), pop(5), push(7, 9):</tex>
{| border = 1; cellspacing = 0; class="wikitable"
|- align = "center"
!index
|!1|!&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;|!&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;|!&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;|!&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;|!&nbsp;&nbsp;&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;|!&nbsp;&nbsp;&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;&nbsp;|!&nbsp;&nbsp;&nbsp;&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp;|!&nbsp;&nbsp;&nbsp;&nbsp;9&nbsp;&nbsp;&nbsp;&nbsp;
|-align = "center"
!value
<br>
В итоге мы имеем доступ ко всем версиям стека за <tex>O(1)</tex> времени и <tex>O(n)</tex> памяти (массив длины n и n самих "стеков").
== См. также==
234
правки

Навигация