【问题标题】:Understanding the recursive call mechanism for implementing a queue using a stack了解使用堆栈实现队列的递归调用机制
【发布时间】:2020-04-30 01:15:27
【问题描述】:

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

#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)如何再次将项目添加到堆栈中,没有底部的元素?

【问题讨论】:

    标签: c++ recursion data-structures stack queue


    【解决方案1】:

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

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

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

    Q. 那么,在提到的if 语句(包括push(x) 语句)之后的代码执行了多少次? 答案: N-1 次。

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

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

    问:下次调用 push(x) 时,x 的值是多少? 答案: 3

    问:剩下的呢? 答案: 4, 5, ... N.

    【讨论】:

    • 这不是问题,但我不明白为什么 push(x) 会推动除 x 之外的所有内容
    • 是的,这是我想要的输出,我只是不明白 push(x) 的工作原理
    • @BlackieRules 了解您应该递归思考。您正在递归调用deQueue()。如果你有一个包含 N 个元素的堆栈(首先压入 1,N 作为最后一个元素),if 部分将执行一次,但else 部分将执行 N-1 次。第一次到达push(x) 部分是在最后一个deQueue() 调用返回时,所以x 等于2。它将被添加到堆栈中。然后你将从下一次调用返回,它会将3 推入堆栈,依此类推。
    • 为什么是N-1次? if (isempty()) 检查它是否为空,N-1 次它不为空,它有 1 个元素
    • @BlackieRules 如果栈的大小为 1,则 if 后面的代码运行 0 次。如果栈的大小为 2,则 if 后面的代码运行 1 次。我已经更新了我的答案,让你更清楚。
    【解决方案2】:

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

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

    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)。

    【讨论】:

      【解决方案3】:

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

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

      几行之后你有:

      if (isempty()){
          return x; 
      }
      

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

      【讨论】:

      • 是的,但是在我返回 x 之后,我得到该项目等于 x,我返回项目
      • 但是我真的不明白为什么return item之前的指令push(x)会推送我弹出的所有项目
      • 输出到底有什么问题?你在期待什么?我问是为了更好地理解这个问题。
      • 输出没问题,我不明白为什么 push(x) 会推送除 x 之外的所有内容
      • // 递归调用 int item = deQueue(); // 将弹出的项目推回堆栈 push(x); // 返回 deQueue() 调用返回项的结果;这里,x 是 1、2 或 3,当它是 1 时 push(x) 推送 2 和 3,当它是 2 时它推送 3 而它是 3 它什么也不推送,我真的不明白为什么
      猜你喜欢
      • 2021-07-08
      • 2014-12-23
      • 2010-10-15
      • 1970-01-01
      • 2020-06-29
      • 2017-01-20
      • 2015-05-15
      • 2018-05-30
      • 1970-01-01
      相关资源
      最近更新 更多