Аналогичный вопрос был задан ранее там , но здесь вопрос обратный, используя две очереди в качестве стека. Вопрос...
Учитывая две очереди с их стандартными операциями ( enqueue
, dequeue
, isempty
, size
), реализовать стек с его стандартными операциями ( pop
, push
, isempty
, size
).
Должно быть две версии решения.
- Версия A : стек должен быть эффективным при выталкивании элемента; а также
- Версия B : стек должен быть эффективным при извлечении элемента.
Алгоритм меня интересует больше, чем какие-либо конкретные языковые реализации. Однако я приветствую решения, выраженные на знакомых мне языках (Ява,c #,питон,vb,javascript,php).
algorithm
data-structures
stack
TechTravelThink
источник
источник
Pop
работает в $ O (1) $ иPush
работает в амортизированном времени $ O (\ sqrt {n}) $.Ответы:
Версия А (эффективный толчок):
Версия B (эффективный поп):
источник
Самый простой (и, возможно, единственный) способ сделать это - поместить новые элементы в пустую очередь, а затем исключить другие и поставить их в ранее пустую очередь. Таким образом, последний всегда находится в начале очереди. Это будет версия B, для версии A вы просто отменяете процесс, удаляя элементы из очереди во вторую очередь, за исключением последней.
Шаг 0:
Шаг 1:
Шаг 2:
Шаг 3:
источник
Мы можем сделать это с помощью одной очереди:
От себя:
n
- количество элементов в очереди, то время удаления и вставки элементаn-1
.поп:
.
Пример реализации:
источник
источник
Можем ли мы использовать одну очередь для реализации стека? Я могу использовать две очереди, но использование одной очереди было бы более эффективным. Вот код:
источник
источник
Вот мой ответ - там, где «поп» неэффективен. Кажется, что все алгоритмы, которые сразу приходят на ум, имеют сложность N, где N - размер списка: выбираете ли вы работать с «всплывающим» или «толкающим».
Алгоритм, при котором списки возвращаются обратно и четвертый, может быть лучше, так как расчет размера не требуется, хотя вам все равно нужно зацикливаться и сравнивать с пустым.
вы можете доказать, что этот алгоритм не может быть записан быстрее, чем N, отметив, что информация о последнем элементе в очереди доступна только через знание размера очереди, и что вы должны уничтожить данные, чтобы добраться до этого элемента, следовательно, вторая очередь .
Единственный способ сделать это быстрее - вообще не использовать очереди.
источник
Вот мое решение, которое работает для O (1) в среднем случае. Есть две очереди:
in
иout
. См. Псевдокод ниже:источник
Как уже упоминалось, разве не поможет одна очередь? Это, вероятно, менее практично, но немного круче.
источник
Вот простой псевдокод, push - O (n), pop / peek - O (1):
источник
Пусть S1 и S2 - два стека, которые будут использоваться при реализации очередей.
Мы следим за тем, чтобы одна очередь всегда была пустой.
Операция push: какая бы очередь не пуста, вставьте в нее элемент.
Push (struct Stack *S, int data) { if(isEmptyQueue(S->Q1) EnQueue(S->Q2, data); else EnQueue(S->Q1, data); }
Сложность времени: O (1)
Pop Operation: передать n-1 элементов в другую очередь и удалить последний из очереди для выполнения операции pop.
`
Сложность времени: время выполнения операции pop - O (n), поскольку каждый раз, когда вызывается pop, мы переносим все элементы из одной очереди в другую.
источник
источник
источник
Вот еще одно решение:
для PUSH: -Добавьте первый элемент в очередь 1. -При добавлении второго элемента и так далее, сначала поставьте элемент в очередь 2, а затем скопируйте все элементы из очереди 1 в очередь2. -для POP просто удалите элемент из очереди, если вы вставили последний элемент.
Так,
}}
Есть одна проблема, не могу разобраться, как переименовать очереди ???
источник
источник
Код Python с использованием только одной очереди
источник
вот полный рабочий код на С #:
Это было реализовано с единой очередью,
От себя:
поп:
источник
Вот очень простое решение, которое использует одну очередь и предоставляет такие функции, как стек.
Итак, в приведенном выше классе с именем "CustomStack" я просто проверяю очередь на пустоту, если она пуста, то вставляю ее, а затем вставляю опеку и затем удаляю вставку. По этой логике первое будет последним. Пример: в очереди я вставил 1 и теперь пытаюсь вставить 2. Второй раз удалите 1 и снова вставьте, чтобы это стало в обратном порядке.
Спасибо.
источник
Ниже приведено очень простое решение Java, которое эффективно поддерживает операцию push.
Алгоритм -
Объявите две очереди q1 и q2.
Операция push - поставить элемент в очередь q1.
Операция Pop - убедитесь, что очередь q2 не пуста. Если он пуст, то удалите из очереди все элементы из q1, кроме последнего, и поместите их в очередь в q2 один за другим. Удалите из очереди последний элемент из q1 и сохраните его как всплывающий элемент. Поменяйте местами очереди q1 и q2. Вернуть сохраненный всплывающий элемент.
Операция просмотра - убедитесь, что очередь q2 не пуста. Если он пуст, то удалите из очереди все элементы из q1, кроме последнего, и поместите их в очередь в q2 один за другим. Удалите из очереди последний элемент из q1 и сохраните его как выбранный элемент. Поместите его обратно в очередь q2 и поменяйте местами очереди q1 и q2. Вернуть сохраненный просматриваемый элемент.
Ниже приведен код для вышеуказанного алгоритма -
источник
Эффективное решение на C #
public class MyStack { private Queue<int> q1 = new Queue<int>(); private Queue<int> q2 = new Queue<int>(); private int count = 0; /** * Initialize your data structure here. */ public MyStack() { } /** * Push element x onto stack. */ public void Push(int x) { count++; q1.Enqueue(x); while (q2.Count > 0) { q1.Enqueue(q2.Peek()); q2.Dequeue(); } var temp = q1; q1 = q2; q2 = temp; } /** * Removes the element on top of the stack and returns that element. */ public int Pop() { count--; return q2.Dequeue(); } /** * Get the top element. */ public int Top() { return q2.Peek(); } /** * Returns whether the stack is empty. */ public bool Empty() { if (count > 0) return false; return true; } }
источник
Вот мое решение ..
Concept_Behind ::
push(struct Stack* S,int data)
:: Эта функция ставит первый элемент в очередь в Q1 и остается в Q2pop(struct Stack* S)
:: если Q2 не пуст, переносит все элементы в Q1 и возвращает последний элемент в Q2, иначе (что означает, что Q2 пуст) переносит все элементы в Q2 и возвращает последний элемент в Q1Efficiency_Behind ::
push(struct Stack*S,int data)
:: O (1) // с момента одиночной постановки в очередь на данныеpop(struct Stack* S)
:: O (n) // поскольку переносит худшие данные n-1 на поп.источник
источник
источник