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

Algorithm 我需要一些帮助来理解如何使用堆栈实现队列,algorithm,recursion,stack,queue,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();

我找到了下面的代码。我只是想知道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; 
    } 
}

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

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()的结果。如果
堆栈
现在为空,则返回
顶部
。如果
堆栈
尚未为空,它将
foo_2
的返回值保存在
结果
中,然后将
顶部
推回到
堆栈
,然后返回保存的
结果

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

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

作为一个快速的说明,考虑队列有三个元素,<代码> 1 ,<代码> 2 ,<代码> 3 < /代码>,其中<代码> 1 <代码>位于队列的前面。因此递归

remove
到达底部后的激活记录如下所示:

top: 1
----
top: 2
result: ? (waiting for result of remove())
----
top: 3
result: ? (waiting for result of remove())
----
在调用堆栈的顶部,
队列
使用的
堆栈
现在为空,因此返回
1
,因此激活记录堆栈更改:

top: 2
result: 1
----
top: 3
result: ? (waiting for result of remove())
----
top: 3
result: 1
----
在此激活记录中,
2
被推回
堆栈
,并返回
结果
,因此激活记录堆栈发生变化:

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

在这个激活记录中,
3
被推回到
堆栈
,然后返回
结果
,激活记录堆栈现在对于
remove

的初始调用是空的,队列将插入后面并从前面移除。但是,队列的前端位于堆栈的底部

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()的结果。如果
堆栈
现在为空,则返回
顶部
。如果
堆栈
尚未为空,它将
foo_2
的返回值保存在
结果
中,然后将
顶部
推回到
堆栈
,然后返回保存的
结果

如果您了解到
foo_1
中的局部函数变量
top
不受调用
foo_2
的影响,那么您已经了解到局部函数变量位于调用
foo_1
的特定保护区中。该保护区有时称为激活记录。对
foo_1
的调用为该调用创建一个激活记录,以保存本地函数状态(如变量、返回值、当前正在运行的代码行等),如果
foo_1
调用另一个函数,一个新的激活被推到当前激活之上,以处理该函数调用的本地函数状态。当该函数调用返回时,它的激活记录弹出,当前激活记录返回调用方的激活记录,
foo_1
。因为推送函数调用的激活记录,并且在函数调用重新启动时弹出激活记录