Два стека могут быть эффективно реализованы с использованием одного массива фиксированного размера: стек № 1 начинается с левого конца и увеличивается вправо, а стек № 2 начинается с правого конца и увеличивается влево. Возможно ли то же самое для трех стеков?
Более конкретно, возможно ли реализовать три стека при следующих условиях:
- У вас есть массив фиксированного размера, который может содержать N объектов.
- Пока сумма трех размеров стека <N, push () не должна завершиться ошибкой.
- Операции push () и pop () должны занимать O (1) времени.
- В дополнение к массиву вы можете использовать только O (1) дополнительное пространство.
Вот примеры решений, которые не удовлетворяют этим требованиям:
- Разбиение массива на 3 фиксированные части и использование каждой части для стека (нарушает 2).
- Аналогично вышеописанному, но с подвижными границами между стопками (нарушает 3).
- Простые реализации на основе связанного списка (нарушает 4).
Я приму нетривиальные алгоритмы или доказательства невозможности, даже если они точно не удовлетворяют всем условиям (1) - (4), например, алгоритм, где push / pop берет O (1) амортизированное время, или где дополнительная память меньше, чем O (N), например, O (log N). Или доказательство невозможности, которое показывает, что, например, доступ менее чем к 5 элементам массива за push / pop невозможен.
источник
Ответы:
Фредман и Голдсмит показали в «Трех стеках» (Журнал Алгоритмов, 1994), чтоΘ(nε) биты потраченного впустую пространства достижимы. Это также минимум, необходимый для массивов размером не менее 16 кв. Я описал простой алгоритм тратыΘ(n−−√) Слова пробела в моем StackOverflow ответят на этот вопрос . Как отметил @ dmitri-urbanowicz в комментариях, это в основном просто обрабатывает массив какn−−√ блоки размера n−−√ где каждый блок используется ровно для одного стека и содержит единственный указатель на следующий блок в этом стеке.
источник
Пусть N будет длиной основного массива. Я могу представить стеки как связанные списки больших чанков, так что общее количество чанков не превышает O (log2 (N)). Поместите третий стек между первыми двумя по индексу N / 2. Итак, у нас есть 3 занятых зоны и 2 свободных. Когда стек не может принять следующий элемент, это означает, что одна свободная область исчерпана. Если другой исчерпан, то вся память исчерпана. В противном случае есть еще одна свободная зона размером не более N / 2. Продолжайте переполненный стек в эту свободную область. так что вся конфигурация напоминает первоначальную компоновку стеков. Поскольку свободной памяти сейчас не больше половины начальной, таких операций связывания будет не более log2 (N). Каждая операция связывания требует фиксированного объема памяти для сохранения предыдущего состояния стека. Так,
источник