我需要一些帮助来理解使用堆栈实现队列

时间:2013-06-13 16:26:33

标签: algorithm recursion stack queue

我找到了下面的代码。我只是想知道remove函数中的“else”部分是如何工作的。如果有人可以为我详细说明这些步骤,我将非常感激。

insert(E value) 
{ 
    stack.push(value); 
} 

E remove() 
{ 
    E top = stack.pop(); 
    if(stack.isEmpty()) 
        return top; 
    else 
    { 
        E result = remove(); 
        stack.push(top); 
        return result; 
    } 
}

1 个答案:

答案 0 :(得分:1)

队列将插入后面并从前面移除。但是,队列的前面位于堆栈的底部。

remove算法递归迭代堆栈直到它到达底部,并作为删除的结果返回该元素。随着递归的展开,它弹出到底部的成员被推回到堆栈中。因此,队列的原始顺序将被恢复,减去队列的前面(这是堆栈的底部)。


在评论中,您写道:

  

我需要帮助来理解这些步骤,例如存储弹出元素的位置以及在递归过程中它们是如何被推送的,以及递归调用如何管理所有这些。

递归函数调用与常规函数调用没有任何根本区别。请考虑以下伪代码:

E foo_2 ()
{
    return stack.pop();
}

E foo_1 ()
{
    E top = stack.pop(); 
    if(stack.isEmpty()) 
        return top; 
    else
    {
        E result = foo_2();
        stack.push(top);
        return result;
    }
}

因此,对foo_1的调用会产生一个名为top的函数局部变量,其结果为stack.pop()。如果stack现在为空,则返回top。如果stack尚未为空,则会将foo_2的返回值保存在result中,然后将top推回stack,然后返回已保存result

如果您了解top中的本地函数变量foo_1不受foo_2调用的影响,那么您已经了解本地函数变量位于特定于的受保护区域中致foo_1的电话。该保护区域有时被称为激活记录。对foo_1的调用为该调用创建了一个激活记录,以保存本地函数状态(如变量,返回值,当前正在运行的代码行等),如果foo_1调用另一个函数,在当前函数之上推送新的激活以处理该函数调用的本地函数状态。当该函数调用返回时,将弹出其激活记录,并且当前激活记录将返回到调用者foo_1的激活记录。由于推送函数调用的激活记录,以及函数调用返回时弹出激活记录,激活记录的结构称为call stack(激活记录也称为stack frames)。

递归调用的唯一技巧是函数调用自身。但是,新的激活记录被推送到调用堆栈,就像常规函数调用一样。

就像快速说明一样,请考虑队列有三个元素123,其中1位于队列的前面。因此,递归remove到达底部后的激活记录将如下所示:

top: 1
----
top: 2
result: ? (waiting for result of remove())
----
top: 3
result: ? (waiting for result of remove())
----

在调用堆栈的顶部,stack使用的queue现在为空,因此返回1,因此激活记录堆栈发生了变化:

top: 2
result: 1
----
top: 3
result: ? (waiting for result of remove())
----

在此激活记录中,2被推回到stack,并返回result,因此激活记录堆栈发生了变化:

top: 3
result: 1
----

在此激活记录中,3被推回到stack,并返回result,并且激活记录堆栈现在相对于初始呼叫为空到remove