Как реализовать очередь с использованием двух стеков?

A — Как перевернуть стек

Чтобы понять, как построить stack очередь с использованием stacks двух стеков, вы должны понимать, как algorithm кристально чисто перевернуть algorithm стек. Помните, как работает queue стопка, она очень похожа data-structure на стопку посуды на вашей queue кухне. Последнее вымытое data-structure блюдо окажется на вершине queue чистой стопки, которая в stacks информатике называется Last data-structure In Ffirst Out (LIFO).

Давайте algorithms представим нашу стопку в stack виде бутылки, как показано algorithm ниже;

Как реализовать очередь с использованием двух стеков?_data-structures

Если мы поместим целые stacks числа 1,2,3 соответственно, то algorithm 3 будет на вершине стека. Поскольку queue 1 будет помещена первой, затем data-structures 2 будет помещена поверх 1. Наконец, 3 algorithm-design будет помещена на вершину queue стека, и последнее состояние stack нашего стека, представленное data-structures в виде бутылки, будет таким, как algorithms показано ниже;

Как реализовать очередь с использованием двух стеков?_queue

Теперь наш algorithm-design стек представлен в виде бутылки, заполненной algorithm значениями 3,2,1. И мы хотим algorithm-design перевернуть стек так, чтобы stacks верхний элемент стека был stack 1, а нижний элемент стека algorithms был 3. Что мы можем сделать? Мы algorithm-design можем взять бутылку и держать stacks ее вверх дном, чтобы все algorithms значения перевернулись по stack порядку?

Как реализовать очередь с использованием двух стеков?_data-structures

Да, мы можем это stack сделать, но это бутылка. Чтобы algorithm выполнить тот же процесс, нам queue нужен второй стек, в котором data-structure будут храниться элементы data-structures первого стека в обратном algorithms порядке. Давайте поместим queue наш заполненный стек слева, а data-structures новый пустой стек справа. Чтобы algorithm-design изменить порядок элементов, мы stacks собираемся извлекать каждый data-structures элемент из левого стека и data-structures помещать их в правый стек. Вы data-structure можете увидеть, что происходит, когда algorithm-design мы это делаем, на изображении data-structures ниже;

Как реализовать очередь с использованием двух стеков?_algorithm-design

Итак, мы знаем, как algorithms перевернуть стек.

B — Использование двух стопок в качестве очереди

В предыдущей algorithm-design части я объяснил, как мы queue можем изменить порядок элементов data-structure стека. Это было важно, потому stack что если мы помещаем элементы stack в стек и извлекаем их из stack него, вывод будет точно в algorithm порядке, обратном порядку stacks очереди. Размышляя над примером, давайте stacks поместим массив целых чисел algorithm {1, 2, 3, 4, 5} в стек. Если мы выталкиваем algorithm элементы и печатаем их до stack тех пор, пока стек не станет algorithm пустым, мы получим массив data-structure в порядке, обратном порядку stack проталкивания, который будет algorithm-design {5, 4, 3, 2, 1} Помните, что для того же queue ввода, если мы удаляем очередь algorithms из очереди, пока очередь algorithm-design не станет пустой , вывод algorithm будет {1, 2, 3, 4, 5}. Таким образом, очевидно, что data-structure для одного и того же порядка data-structure ввода элементов вывод очереди algorithms в точности противоположен algorithm-design выводу стека. Поскольку мы algorithm знаем, как перевернуть стек, используя stack дополнительный стек, мы можем data-structures построить очередь, используя algorithm два стека.

Наша модель очереди stacks будет состоять из двух стеков. Один data-structures стек будет использоваться stack для операции enqueue (стек №1 слева algorithms будет называться входным queue стеком), другой стек будет data-structure использоваться для операции algorithms dequeue (стек №2 справа будет называться data-structures выходным стеком). Куча). Посмотрите data-structure на изображение ниже;

Как реализовать очередь с использованием двух стеков?_algorithms

Наш псевдокод stacks приведен ниже;


Операция постановки в очередь

Push every input element to the Input Stack

Операция удаления из очереди

If ( Output Stack is Empty)
    pop every element in the Input Stack
    and push them to the Output Stack until Input Stack is Empty

pop from Output Stack

Поставим в queue очередь целые числа {1, 2, 3} соответственно. Целые queue числа будут помещаться в stacks Входной стек (Стек №1), расположенный слева;

Как реализовать очередь с использованием двух стеков?_algorithm-design

Тогда algorithm что произойдет, если мы выполним algorithms операцию удаления из очереди? Всякий data-structures раз, когда выполняется операция algorithm удаления из очереди, очередь algorithms будет проверять, пуст ли stacks выходной стек или нет (см. псевдокод stacks выше). Если выходной стек stack пуст, то входной стек будет data-structure извлечен на выходе, поэтому stack элементы входного стека будет data-structure инвертирован. Перед возвратом algorithm-design значения состояние очереди algorithm-design будет следующим:

Как реализовать очередь с использованием двух стеков?_algorithm-design

Проверьте algorithm порядок элементов в выходном algorithms стеке (стек № 2). Очевидно, что queue мы можем извлекать элементы queue из выходного стека, чтобы algorithms результат был таким же, как queue если бы мы были исключены data-structure из очереди. Таким образом, если stack мы выполним две операции algorithms удаления из очереди, сначала algorithm-design мы получим {1, 2} соответственно. Тогда stack элемент 3 будет единственным algorithms элементом выходного стека, а data-structures входной стек будет пуст. Если stacks мы поставим в очередь элементы data-structures 4 и 5, то состояние очереди stacks будет следующим;

Как реализовать очередь с использованием двух стеков?_algorithm-design

Теперь выходной data-structure стек не пуст, и если мы выполним stack операцию удаления из очереди, из data-structure выходного стека будут извлечены data-structure только 3. Тогда состояние data-structures будет выглядеть так, как stacks показано ниже;

Как реализовать очередь с использованием двух стеков?_queue

Опять же, если stacks мы выполним еще две операции algorithm-design удаления из очереди, при data-structures первой операции удаления algorithm-design из очереди очередь проверит, пуст stacks ли выходной стек, что верно. Затем queue извлеките элементы входного data-structures стека и поместите их в выходной stacks стек, пока входной стек не stack станет пустым, тогда состояние stacks очереди будет таким, как data-structure показано ниже;

Как реализовать очередь с использованием двух стеков?_algorithms

Легко видеть, что algorithm-design результат двух операций удаления data-structures из очереди будет {4, 5}

C — Реализация очереди, построенной из двух стеков

Вот реализация algorithm на Java. Я не собираюсь использовать stacks существующую реализацию стека, поэтому data-structures в этом примере я заново изобрету algorithms колесо;

C – 1) Класс MyStack: простая реализация стека

public class MyStack {

    // inner generic Node class
    private class Node {
        T data;
        Node next;

        public Node(T data) {
            this.data = data;
        }
    }

    private Node head;
    private int size;

    public void push(T e) {
        Node newElem = new Node(e);

        if(head == null) {
            head = newElem;
        } else {
            newElem.next = head;
            head = newElem;     // new elem on the top of the stack
        }

        size++;
    }

    public T pop() {
        if(head == null)
            return null;

        T elem = head.data;
        head = head.next;   // top of the stack is head.next

        size--;

        return elem;
    }

    public int size() {
        return size;
    }

    public boolean isEmpty() {
        return size == 0;
    }

    public void printStack() {
        System.out.print("Stack: ");

        if(size == 0)
            System.out.print("Empty !");
        else
            for(Node temp = head; temp != null; temp = temp.next)
                System.out.printf("%s ", temp.data);

        System.out.printf("\n");
    }
}

C - 2) Класс MyQueue: реализация очереди с использованием двух стеков

public class MyQueue {

    private MyStack inputStack;      // for enqueue
    private MyStack outputStack;     // for dequeue
    private int size;

    public MyQueue() {
        inputStack = new MyStack<>();
        outputStack = new MyStack<>();
    }

    public void enqueue(T e) {
        inputStack.push(e);
        size++;
    }

    public T dequeue() {
        // fill out all the Input if output stack is empty
        if(outputStack.isEmpty())
            while(!inputStack.isEmpty())
                outputStack.push(inputStack.pop());

        T temp = null;
        if(!outputStack.isEmpty()) {
            temp = outputStack.pop();
            size--;
        }

        return temp;
    }

    public int size() {
        return size;
    }

    public boolean isEmpty() {
        return size == 0;
    }

}

C – 3) Демонстрационный код

public class TestMyQueue {

    public static void main(String[] args) {
        MyQueue queue = new MyQueue<>();

        // enqueue integers 1..3
        for(int i = 1; i <= 3; i++)
            queue.enqueue(i);

        // execute 2 dequeue operations 
        for(int i = 0; i < 2; i++)
            System.out.println("Dequeued: " + queue.dequeue());

        // enqueue integers 4..5
        for(int i = 4; i <= 5; i++)
            queue.enqueue(i);

        // dequeue the rest
        while(!queue.isEmpty())
            System.out.println("Dequeued: " + queue.dequeue());
    }

}

C – 4) Пример вывода

Dequeued: 1
Dequeued: 2
Dequeued: 3
Dequeued: 4
Dequeued: 5

algorithm

data-structures

stack

queue

2022-10-22T08:11:07+00:00