我有一些在其實現中使用遞歸的代碼。 profiler which I'm using不適合遞歸函數調用,所以我想重寫它是非遞歸的。避免遞歸
當前的代碼是這樣的:
void Parse(Foo foo)
{
A()
for (;;)
{
B();
if (C())
return;
if (D())
{
Run();
}
E();
}
}
void Run()
{
X();
if (Y())
{
Parse();
}
Z();
}
以上是僞代碼。字母A,B,C,D,E,X,Y和Z是方法,Parse()和Run()也是。爲了簡單起見,我省略了各種參數和對象解引用(例如,運行是對象實例的一種方法,並且它需要一些參數)。
無論如何,我的問題是,我怎麼把它變成非遞歸的代碼?
等效的非遞歸代碼,在我看來是:
void Parse(Foo foo)
{
//create a local stack variable to emulate recursion
Stack<Foo> foos = new Stack<Foo>();
foos.Add(foo());
start_subroutine:
A()
for (;;)
{
B();
if (C())
{
//instead of returning from a recursive call
if (foos.Count > 1)
{
foo = foos.Pop();
goto end_subroutine;
}
return;
}
if (D())
{
//instead of invoking Run as a subroutine, bring its functionality inline
//Run();
X();
if (Y())
{
//instead of calling self recursively
//Parse();
//push onto a local stack variable and jump
foos.Add(foo);
goto start_subroutine;
}
end_subroutine:
Z();
}
E();
}
}
我可以接受這樣做,但我不知道如何做到這一點不使用goto語句;我不記得有人看到有人寫道,這是goto必要時的情況之一。
重新編寫代碼以適應探查器的弱點的想法是我最近遇到的最奇怪的之一。 – 2009-08-02 22:16:43
我會將這種情況列入越來越多的'奇怪的東西,C#人做' –
2009-08-02 22:23:22
@Dirk - 我會說這是追求自由軟件,導致他走下了這條道路。 – ChrisF 2009-08-02 22:35:02