我想使用堆栈和循环将以下程序转换为非递归代码:
void write(int n) {
if (n>0) {
write(n-1);
cout << n << " ";
write(n-1);
}
}
以下是我正在使用的代码,但目前无效,我不知道为什么:
stack<int> S;
S.push(n);
while (not S.empty()) {
int k = S.top();
S.pop()
if (k>0) {
S.push(k-1);
cout<<k<<" ";
S.push(k-1);
}
}
它不起作用,我不知道如何模拟该递归。我认为将相应的递归调用推入堆栈就足够了。
感谢
答案 0 :(得分:1)
你的问题是第一次调用write(n - 1)
发生在输出之前,但弹出值的评估发生在它之后。
您可以让堆栈模拟实际的激活记录:
enum Action
{
Call, Write
};
struct Record
{
Action action;
int arg;
};
stack<Record> S;
S.push({Call, n});
while (not S.empty()) {
auto rec = S.top();
S.pop()
switch (rec.action) {
case Call:
if (rec.arg > 0) {
S.push({Call, rec.arg - 1}); // corresponds to 2nd write() call
S.push({Write, rec.arg});
S.push({Call, rec.arg - 1}); // corresponds to 1st write() call
}
break;
case Write:
std::cout << rec.arg << ' ';
break;
}
}
答案 1 :(得分:1)
问题是你做了2次推送到堆栈,但在打印所有调用链之前,首先递归调用write()
。
这是递归调用的迭代等价物:
std::stack<int> S;
for( int i = n; i > 0; --i )
S.push( i );
while( not S.empty() ) {
int k = S.top();
S.pop();
for( int i = k - 1; i > 0; --i ) {
S.push( i );
}
std::cout << k << " ";
}