Algorithm 我需要一些帮助来理解如何使用堆栈实现队列
我找到了下面的代码。我只是想知道remove函数中的“else”部分是如何工作的。如果有人能为我详细说明这些步骤,我将不胜感激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();
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
。因为推送函数调用的激活记录,并且在函数调用重新启动时弹出激活记录