Login or e-mail Password   

Replacing Recursion With a Stack

In Jeff Atwood’s infamous FizzBuzz post , he quotes Dan Kegel who mentions. Less trivially, I’ve interviewed many candidates who can’t use recursion to solve a...
Views: 2.120 Created 09/12/2007
In Jeff Atwood’s infamous FizzBuzz post, he quotes Dan Kegel who mentions.

Less trivially, I’ve interviewed many candidates who can’t use recursion to solve a real problem.

A programmer who doesn’t know how to use recursion isn’t necessarily such a bad thing, assuming the programmer is handy with the Stack data structure. Any recursive algorithm can be replaced with a non-recursive algorithm by using a Stack.

As an aside, I would expect any developer who knew how to use a stack in this way would probably have no problem with recursion.

After all, what is a recursive method really doing under the hood but implicitely making use of the call stack?

I’ll demonstrate a method that removes recursion by explicitely using an instance of the Stack class, and I’ll do so using a common task that any ASP.NET developer might find familiar. I should point out that I’m not recommending that you should or shouldn’t do this with methods that use recursion. I’m merely pointing out that you can do this.

In ASP.NET, a Web Page is itself a control (i.e. the Page class inherits from Control), that contains other controls. And those controls can possibly contain yet other controls, thus creating a tree structure of controls.

So how do you find a control with a specific ID that could be nested at any level of the control hierarchy?

Well the recursive version is pretty straightforward and similar to other methods I've written before.

public Control FindControlRecursively(Control root, string id)
{
Control current = root;

if (current.ID == id)
return current;

foreach (Control control in current.Controls)
{
Control found = FindControlRecursively(control, id);
if (found != null)
return found;
}
return null;
}

The recursion occures when we call FindControlRecursively within this method. Essentially what is happening (and this is a simplification) when we call that method is that our current execution point is pushed onto the call stack and the runtime starts executing the code for the internal method call. When that method finally returns, we pop our place from the stack and continue executing.

Rather than try to explain, let me just show you the non-recursive version of this method using a Stack.

public Control FindControlSansRecursion(Control root
, string id)
{
//seed it.
Stack<Control> stack = new Stack<Control>();
stack.Push(root);

while(stack.Count > 0)
{
Control current = stack.Pop();
if (current.ID == id)
return current;

foreach (Control control in current.Controls)
{
stack.Push(control);
}
}

//didn’t find it.
return null;
}

One thing to keep in mind is that both of these implementations assume that we won’t run into a circular reference problem in which a child control contains an ancestor node.

For the System.Web.UI.Control class we safe in making this assumption. If you try and create a circular reference, a StackOverflowException is thrown. The following code demonstrates this point.

Control control = new Control();
control.Controls.Add(new Control());
// This line will throw a StackOverflowException.
control.Controls[0].Controls.Add(control);

If the hierarchical structure you are using does allow circular references, you’ll have to keep track of which nodes you’ve already seen so that you don’t get caught in any infinitel loops.

Similar articles


6
comments: 0 | views: 34963
8
comments: 4 | views: 12790
7
comments: 0 | views: 3665
6
comments: 0 | views: 2002
6
comments: 1 | views: 1016
5
comments: 1 | views: 1135
 
Author
Article

Related topics






No messages


Add your opinion
You must be logged in to write a comment. If you're not a registered member, please register. It takes only few seconds, and you get an access to additional functions .
 


About EIOBA
Articles
Explore
Publish
Community
Statistics
Users online: 62
Registered: 61.232
Comments: 444
Articles: 66.448
© 2005-2014 EIOBA group.