了解使用堆栈实现队列的递归调用机制

Understanding the recursive call mechanism for implementing a queue using a stack

本文关键字:递归 调用 机制 队列 实现 堆栈 了解      更新时间:2023-10-16

我正在尝试使用堆栈和递归调用实现队列,这是类堆栈和一些方法:

#include <iostream>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
class Node{
public:
int data;
Node* next;
};
Node* top = NULL;
void push(int data){
Node* node = new Node();
node->data = data;
node->next = top;
top = node;
cout << "pushato: " << node->data << "n";
};
bool isempty(){
if(top==NULL){
return true;
}else{
return false;
}
};
void pop(){
if(isempty()){
cout << "lo stack e vuoto.n";
}else{
Node* ptr = top;
top = top->next;
cout << "eliminato: " << ptr->data << "n";
delete(ptr);
}
};
Node* showtop(){
if(!isempty()){
cout << "l'elemento del top e: " << top->data << "n";
return top;
}else{
cout << "lo stack e vuoto.n";
}
};

这是队列的结构:

struct Queue{
void enQueue(int x) 
{ 
push(x); 
} 
int deQueue() 
{ 
if (isempty()) { 
cout << "Q is empty"; 
exit(0); 
} 
// pop an item from the stack 
int x = showtop()->data; 
pop(); 
// if stack becomes empty, return 
// the popped item 
if (isempty()){
return x; 
}

// recursive call 
int item = deQueue(); 
// push popped item back to the stack 
push(x);
// return the result of deQueue() call 
return item; 
} 
}; 

这是主要的:

int main(int argc, char** argv) {
Queue q; 
q.enQueue(1); 
q.enQueue(2); 
q.enQueue(3); 
cout << q.deQueue() << 'n'; 
cout << q.deQueue() << 'n'; 
cout << q.deQueue() << 'n'; 
return 0;
}

这是输出:

pushed:1
pushed:2
pushed:3
popped 3
popped 2
popped 1
pushed 2
pushed 3
1
popped 3
popped 2
pushed 3
2
popped 3
3

代码工作正常,输出完全正确,但我真的不明白为什么在递归调用结束后,我在 if 中返回x,所有以前的项目都被推入堆栈?push(x)如何在没有底部元素的情况下再次将项目添加到堆栈中?

要了解代码如何通过push(x)将元素推送到堆栈中,请考虑以下关于包含 N 个元素的队列的问答,其中 1 作为底部元素,N 作为顶部元素:

问:调用deQueue()函数多少次?答:N次。第一次从main()和 N-1 次递归。

问:deQueue()方法中有一个返回xif语句。此if语句的条件满足多少次?答:只有一次。

问:那么,上述if语句(包括push(x)语句(后面的代码执行了多少次?答:N-1倍。

问:第一次执行push(x)行是什么时候?答:它在其前一条语句时首次执行,即int item = deQueue();已正常返回,没有任何递归。

问:在这种情况下(第一次调用push(x)(,x的价值是多少?答:如果deQueue()正常返回且不再重复,则x的值将为 1。但对于之前的最新递归,x的值为 2。

问:下一次调用推送(x)x值是多少?答案:3

问:其余的呢?答案:4, 5, ...N.

它通过临时存储元素直到到达底部来"弹出"堆栈的底部元素,然后在递归调用返回时将它们放回原处。

删除一个项目并保存以供以后使用:

int x = showtop()->data; 
pop(); 

如果是底部项目,则返回它:

if (isempty()){
return x; 
}

否则,让递归调用删除底部项目并将其提供给我们:

int item = deQueue(); 

现在堆栈包含除底部项目(item(和我们删除的项目(x(之外的所有项目,因此我们将删除的项目放回顶部:

push(x);

并传递我们从递归中获得的底部项目:

return item; 

我怀疑让您感到困惑的是,deQueue可能会将值返回到先前对deQueue的调用,而不是直接返回到main
(从递归返回不像退出循环。

更具体地说,如果您的队列是

1 2 3

第一次调用将首先将1存储在x中,然后递归(堆栈现在2 3(。
第二个调用将2存储在其x和递归 (3( 中。
第三次调用删除3,留下一个空堆栈,并将3返回给其调用方。
然后,第二个调用推回它所花费的2并返回3(2(。
然后,第一个调用推回1并返回3(1 2(。

在你的deQueue()函数中,你有这段代码(如果为真(退出程序:

if (isempty()) { 
cout << "Q is empty"; 
exit(0); 
} 

几行之后,您就有:

if (isempty()){
return x; 
}

这永远无法执行,因为您之前调用了exit(0)