简体   繁体   中英

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

I'm trying to implement a Queue using a stack and recursive call, this is the class Stack and a few methods:

#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";
    }
};

And this is the struct for the Queue:

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; 
    } 
}; 

This is the main:

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;
}

And this is the output:

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

The code works fine and the output is totally correct, but I don't really get why after the recursive call ends and I return x in the if, all of the previous items get pushed into the stack? How push(x) adds the items into the stack again, without the element at the bottom?

To understand how the code pushes elements into the stack by means of push(x) , consider the following Q/As regarding a queue with N elements inside it, with 1 as the bottom element and N as the top one:

Q: How many times the deQueue() function is called? Answer: N times. The first time from main() and N-1 times recursively.

Q: There is an if statement in the deQueue() method which returns x . How many times the condition of this if statement satisfies? Answer: Only once.

Q. So, how many times the code after the mentioned if statement (including the push(x) statement) is executed? Answer: N-1 times.

Q: What is the first time that the push(x) line is executed? Answer: It executes for the first time when its previous statement, ie int item = deQueue(); has returned normally without any recursions.

Q: In that case (first call of push(x) ), what will be the value of x ? Answer: If the deQueue() return normally and do not recur, the value of x will be 1. But for the latest recursion before that, the value of x is 2.

Q: And what value will be the value of x for the next call to push (x) ? Answer: 3

Q: And for the rest? Answer: 4, 5, ... N.

In your deQueue() function you have this piece of code which (if true) exits the program:

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

A few lines later you have:

if (isempty()){
    return x; 
}

That can never be executed because you called exit(0) before.

It "pops" the bottom element of the stack by temporarily storing an element until it reaches the bottom, then putting them back as the recursive calls return.

Remove one item and save it for later:

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

If it was the bottom item, return it:

if (isempty()){
    return x; 
}

Otherwise, let a recursive call remove the bottom item and give it to us:

 int item = deQueue(); 

Now the stack contains all the items except the bottom one ( item ) and the one we removed ( x ), so we put the one we removed back on top:

push(x);

and pass along the bottom item that we got from recursing:

return item; 

I suspect that what's tripping you up is that deQueue might return the value to a previous call to deQueue , not directly to main .
(Returning from a recursion is not like exiting a loop.)

More concretely, if your queue is

1 2 3

The first call will first store 1 in x , then recurse (the stack is now 2 3 ).
The second call stores 2 in its x and recurses ( 3 ).
The third call removes the 3 , leaving an empty stack, and returns the 3 to its caller.
The second call then pushes back the 2 it took and returns 3 ( 2 ).
Then, the first call pushes back 1 and also returns 3 ( 1 2 ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM