Персистентный стек — различия между версиями
(→Реализация на списке) |
(→Алгоритм) |
||
Строка 1: | Строка 1: | ||
== Алгоритм == | == Алгоритм == | ||
+ | '''struct''' '''Node''': | ||
+ | '''T''' value | ||
+ | '''Node''' prev | ||
=== Реализация на массиве === | === Реализация на массиве === | ||
Заведем массив запросов, модифицирующих стек.<br> | Заведем массив запросов, модифицирующих стек.<br> | ||
Строка 10: | Строка 13: | ||
s[s.top].prev = i | s[s.top].prev = i | ||
* <tex>\mathrm{pop}(i)</tex> {{---}} возвращает значение, хранящееся в элементе с номером <tex>i</tex> и копирует элемент, предыдущий для него, | * <tex>\mathrm{pop}(i)</tex> {{---}} возвращает значение, хранящееся в элементе с номером <tex>i</tex> и копирует элемент, предыдущий для него, | ||
− | результирующий стек будет иметь номер <tex> n + 1 </tex> | + | результирующий стек будет иметь номер <tex> n + 1 </tex>, |
'''T''' pop(i : '''uint'''): | '''T''' pop(i : '''uint'''): | ||
'''Node''' k = s[i] | '''Node''' k = s[i] | ||
Строка 25: | Строка 28: | ||
k.value = x | k.value = x | ||
k.prev = i | k.prev = i | ||
− | top = k | + | s.top = k |
− | + | '''return''' s | |
* <tex>\mathrm{pop}(i)</tex> {{---}} возвращает значение, хранящееся в узле <tex>i</tex> и копирует элемент, предыдущий для него. | * <tex>\mathrm{pop}(i)</tex> {{---}} возвращает значение, хранящееся в узле <tex>i</tex> и копирует элемент, предыдущий для него. | ||
− | '''pair <T, Stack>''' pop(i : '''Node'''): | + | '''pair<T, Stack>''' pop(i : '''Node'''): |
'''Node''' k = i.prev | '''Node''' k = i.prev | ||
push(k.prev, k.value) | push(k.prev, k.value) | ||
+ | '''return''' pair(i.value, s) | ||
== Пример == | == Пример == |
Версия 22:52, 6 июня 2015
Содержание
Алгоритм
struct Node: T value Node prev
Реализация на массиве
Заведем массив запросов, модифицирующих стек.
У каждого элемента массива будет поля: значение в вершине стека и индекс предыдущей версии стека.
Тогда операции 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): Node k = s[i] k = s[k.prev] push(k.prev, k.value)
Реализация на списке
Обойдёмся без массива. Будем хранить состояния в узлах. Будем возвращать пользователю информацию о текущей вершине.
У каждого узла будет поля: значение в вершине стека и ссылка на предыдущую версию стека.
- — добавляет элемент в стек узла ,
Stack push(i : Node, x : T): k.value = x k.prev = i s.top = k return s
- — возвращает значение, хранящееся в узле и копирует элемент, предыдущий для него.
pair<T, Stack> pop(i : Node): Node k = i.prev push(k.prev, k.value) return pair(i.value, s)
Пример
Пусть изначально у нас есть один пустой стек. Запишем его в массив.
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 |
В итоге мы имеем доступ ко всем версиям стека за времени и памяти.
Пример задачи
N детей по очереди лепят снеговиков. Первый ребенок слепил снеговик из одного шара радиусом R1. Каждый следующий ребенок слепил такого же снеговика, как и предыдущий, но подумав немного либо добавил шар радиусом Ri, либо разрушил верхний, уже имеющийся шар. Гарантируется, что все снеговики имеют строго положительное число шаров. Входные данные — N, информация о каждом из детей о том, разрушил ли он последний шар, либо добавил свой (тогда дается и его радиус). Далее дается набор из K чисел в пределах от 1-го до N, для каждого требуется вывести последовательность шаров в снеговике с таким номером. Ограничение на N и K — миллион.