Algorithm 使用push&;堆栈的pop操作

Algorithm 使用push&;堆栈的pop操作,algorithm,stack,queue,Algorithm,Stack,Queue,在互联网上搜索时,我找到了许多关于如何使用两个堆栈实现队列的答案。 但是,如何仅使用堆栈的push和pop操作来实现队列呢。堆栈的推操作可以与队列的排队操作类似的方式使用,因为两者都在末尾追加数据。但问题在于执行deque操作,因为队列以FIFO方式工作,而堆栈以LIFO方式工作。 我知道在某些地方,我们将不得不使用递归,就像只使用堆栈的push和pop操作来反转堆栈一样。 我正在编写的伪代码用于使用堆栈的push()、pop()&ismptystack()函数反转堆栈,它是 void reve

在互联网上搜索时,我找到了许多关于如何使用两个堆栈实现队列的答案。
但是,如何仅使用堆栈的push和pop操作来实现队列呢。堆栈的操作可以与队列的排队操作类似的方式使用,因为两者都在末尾追加数据。但问题在于执行deque操作,因为队列以FIFO方式工作,而堆栈以LIFO方式工作。
我知道在某些地方,我们将不得不使用递归,就像只使用堆栈的push和pop操作来反转堆栈一样。 我正在编写的伪代码用于使用堆栈的push()、pop()&ismptystack()函数反转堆栈,它是

void reverseStack(Stack s){
if(isEmptyStack(s))
return

temp=pop(s)
reverseStack(s)
push(s,temp)
}

不需要递归就可以做到这一点

1) 让我们维护两个堆栈s1和s2(最初都是空的)

2) 排队:推送到堆栈s1

3) deque:如果s2是空的,而s1不是空的,则从s1弹出元素并将它们推送到s2。 返回pop(s2)


此解决方案具有O(n)时间复杂性(对于n个查询),因为每个元素只被推送两次(到s1和s2),并且只被弹出两次。

不需要递归就可以做到这一点

1) 让我们维护两个堆栈s1和s2(最初都是空的)

2) 排队:推送到堆栈s1

3) deque:如果s2是空的,而s1不是空的,则从s1弹出元素并将它们推送到s2。 返回pop(s2)


此解决方案的时间复杂度为O(n)(对于n个查询),因为每个元素只被推送两次(到s1和s2)和弹出两次。

我们不必使用递归。 事实上,使用两个堆栈实现队列并不困难

但在这里我们只能使用堆栈的标准操作——这意味着只有向后推、从前面查看/弹出、大小和为空操作才有效

需要两个堆栈:我们可以将它们分别命名为输入和输出。
输入用于将每个元素推入模拟队列(您的目标)。
当您想要从模拟队列中弹出元素,或获取队列的前端时。您应该检查输出堆栈是否为空,如果输出为空,则应该将输入堆栈中的所有元素弹出到输出中。 然后,输入中的前一个元素现在位于输出堆栈的顶部

C++代码如下:s1表示输入堆栈,s2表示输出堆栈

class Queue {
public:
    // Push element x to the back of queue.
    void push(int x) {
        s1.push(x);
    }

    // Removes the element from in front of queue.
    void pop(void) {
        assert(!s1.empty()||!s2.empty());
        if(!s2.empty()) s2.pop();
        else {
            while(!s1.empty()){
                int t=s1.top();
                s1.pop();
                s2.push(t);
            }
            s2.pop();
        }
    }

    // Get the front element.
    int peek(void) {
        assert(!s1.empty()||!s2.empty());
         if(!s2.empty()) {
             return s2.top();
         }
        else {
            while(!s1.empty()){
                int t=s1.top();
                s1.pop();
                s2.push(t);
            }
             return s2.top();
        }
    }

    // Return whether the queue is empty.
    bool empty(void) {
        return s1.empty()&&s2.empty();
    }
private:
    stack<int> s1;
    stack<int> s2;
};`
类队列{
公众:
//将元素x推到队列的后面。
无效推送(整数x){
s1.推(x);
}
//从队列前面移除元素。
void pop(void){
断言(!s1.empty()| |!s2.empty());
如果(!s2.empty())s2.pop();
否则{
而(!s1.empty()){
int t=s1.top();
s1.pop();
s2.推力(t);
}
s2.pop();
}
}
//获取前面的元素。
内部窥视(无效){
断言(!s1.empty()| |!s2.empty());
如果(!s2.empty()){
返回s2.top();
}
否则{
而(!s1.empty()){
int t=s1.top();
s1.pop();
s2.推力(t);
}
返回s2.top();
}
}
//返回队列是否为空。
bool empty(void){
返回s1.empty()和&s2.empty();
}
私人:
堆栈s1;
堆栈s2;
};`

此外,根据您的语言,您可以使用list或deque模拟堆栈。

我们不必使用递归。 事实上,使用两个堆栈实现队列并不困难

但在这里我们只能使用堆栈的标准操作——这意味着只有向后推、从前面查看/弹出、大小和为空操作才有效

需要两个堆栈:我们可以将它们分别命名为输入和输出。
输入用于将每个元素推入模拟队列(您的目标)。
当您想要从模拟队列中弹出元素,或获取队列的前端时。您应该检查输出堆栈是否为空,如果输出为空,则应该将输入堆栈中的所有元素弹出到输出中。 然后,输入中的前一个元素现在位于输出堆栈的顶部

C++代码如下:s1表示输入堆栈,s2表示输出堆栈

class Queue {
public:
    // Push element x to the back of queue.
    void push(int x) {
        s1.push(x);
    }

    // Removes the element from in front of queue.
    void pop(void) {
        assert(!s1.empty()||!s2.empty());
        if(!s2.empty()) s2.pop();
        else {
            while(!s1.empty()){
                int t=s1.top();
                s1.pop();
                s2.push(t);
            }
            s2.pop();
        }
    }

    // Get the front element.
    int peek(void) {
        assert(!s1.empty()||!s2.empty());
         if(!s2.empty()) {
             return s2.top();
         }
        else {
            while(!s1.empty()){
                int t=s1.top();
                s1.pop();
                s2.push(t);
            }
             return s2.top();
        }
    }

    // Return whether the queue is empty.
    bool empty(void) {
        return s1.empty()&&s2.empty();
    }
private:
    stack<int> s1;
    stack<int> s2;
};`
类队列{
公众:
//将元素x推到队列的后面。
无效推送(整数x){
s1.推(x);
}
//从队列前面移除元素。
void pop(void){
断言(!s1.empty()| |!s2.empty());
如果(!s2.empty())s2.pop();
否则{
而(!s1.empty()){
int t=s1.top();
s1.pop();
s2.推力(t);
}
s2.pop();
}
}
//获取前面的元素。
内部窥视(无效){
断言(!s1.empty()| |!s2.empty());
如果(!s2.empty()){
返回s2.top();
}
否则{
而(!s1.empty()){
int t=s1.top();
s1.pop();
s2.推力(t);
}
返回s2.top();
}
}
//返回队列是否为空。
bool empty(void){
返回s1.empty()和&s2.empty();
}
私人:
堆栈s1;
堆栈s2;
};`

此外,根据您的语言,您可以使用list或deque模拟堆栈。

LMGTFY:Easy。你作弊。将调用堆栈用作第二个堆栈。也称为recursion.LMGTFY:简单。你作弊。将调用堆栈用作第二个堆栈。也称为递归。