Персистентный стек — различия между версиями
(→Источники информации) |
(→Эффективная реализация) |
||
Строка 1: | Строка 1: | ||
== Эффективная реализация == | == Эффективная реализация == | ||
− | + | Заведем массив запросов, модифицирующих стек.<br> | |
У каждого элемента массива будет <tex>2</tex> поля: значение в вершине стека и индекс предыдущей версии стека.<br> | У каждого элемента массива будет <tex>2</tex> поля: значение в вершине стека и индекс предыдущей версии стека.<br> | ||
Тогда операции push и pop будут иметь следующий вид:<br> | Тогда операции push и pop будут иметь следующий вид:<br> | ||
− | * <tex> \mathrm{push}(i, x)</tex> {{---}} добавляет элемент | + | * <tex> \mathrm{push}(i, x)</tex> {{---}} добавляет элемент <tex>x</tex> в стек с номером <tex>i</tex>, результирующий стек будет иметь номер <tex> n + 1 </tex>. |
'''function''' push(i : '''uint''', x : '''T'''): | '''function''' push(i : '''uint''', x : '''T'''): | ||
s.top = s.top + 1 | s.top = s.top + 1 | ||
s[s.top].value = x | s[s.top].value = x | ||
s[s.top].prev = i | s[s.top].prev = i | ||
− | * <tex>\mathrm{pop}(i)</tex> {{---}} возвращает значение, хранящееся в элементе с номером i и копирует элемент, предыдущий для него | + | * <tex>\mathrm{pop}(i)</tex> {{---}} возвращает значение, хранящееся в элементе с номером <tex>i</tex> и копирует элемент, предыдущий для него, |
результирующий стек будет иметь номер <tex> n + 1 </tex>. | результирующий стек будет иметь номер <tex> n + 1 </tex>. | ||
'''T''' pop(i : '''uint'''): | '''T''' pop(i : '''uint'''): |
Версия 21:29, 5 июня 2015
Эффективная реализация
Заведем массив запросов, модифицирующих стек.
У каждого элемента массива будет поля: значение в вершине стека и индекс предыдущей версии стека.
Тогда операции push и pop будут иметь следующий вид:
- — добавляет элемент в стек с номером , результирующий стек будет иметь номер .
function push(i : uint, x : T): s.top = s.top + 1 s[s.top].value = x s[s.top].prev = i
- — возвращает значение, хранящееся в элементе с номером и копирует элемент, предыдущий для него,
результирующий стек будет иметь номер
.T pop(i : uint): T k = s[i] k = s[k.prev] push(k.prev, k.value)
Пример
- Пусть изначально у нас есть один пустой стек. Запишем его в массив.
index | 1 |
---|---|
value | |
prev |
- Далее выполним . Создается новая вершина со значением , ссылающаяся на 1-ую, помещаем ее во 2-ую ячейку массива:
index | 1 | 2 |
---|---|---|
value | 3 | |
prev | 1 |
- Аналогично выполним :
index | 1 | 2 | 3 |
---|---|---|---|
value | 3 | 5 | |
prev | 1 | 2 |
- Выполним . он возвращает и копирует 2-ую вершину.
index | 1 | 2 | 3 | 4 |
---|---|---|---|---|
value | 3 | 5 | 3 | |
prev | 1 | 2 | 1 |
- Так будет выглядеть массив после последовательности операций
index | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
---|---|---|---|---|---|---|---|---|---|
value | 3 | 5 | 3 | 6 | 1 | 5 | 9 | ||
prev | 1 | 2 | 1 | 3 | 5 | 2 | 7 |
В итоге мы имеем доступ ко всем версиям стека за времени и памяти.