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:简单。你作弊。将调用堆栈用作第二个堆栈。也称为递归。