Software Design
 
Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
User Name:
Password:
Remember me
Go Back   Dev Shed ForumsProgramming Languages - MoreSoftware Design

Reply
Add This Thread To:
  Del.icio.us   Digg   Google   Spurl   Blink   Furl   Simpy   Y! MyWeb 
Thread Tools Search this Thread Rate Thread Display Modes
 
Unread Dev Shed Forums Sponsor:
  #1  
Old February 15th, 2004, 12:55 AM
ktoz ktoz is offline
Contributing User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Apr 2003
Posts: 473 ktoz User rank is Sergeant Major (2000 - 5000 Reputation Level)ktoz User rank is Sergeant Major (2000 - 5000 Reputation Level)ktoz User rank is Sergeant Major (2000 - 5000 Reputation Level)ktoz User rank is Sergeant Major (2000 - 5000 Reputation Level)ktoz User rank is Sergeant Major (2000 - 5000 Reputation Level)ktoz User rank is Sergeant Major (2000 - 5000 Reputation Level) 
Time spent in forums: 1 Week 3 Days 4 h 51 m 32 sec
Reputation Power: 35
Converting a recursive algorithm to an iterative one

I'm trying to write a C routine to calculate the distinct partitions of an integer and am running into stack overflows in a recursive routine for numbers greater than 150. I read somewhere that every recursive algorithm can be converted to an iterative one but can't seem to think of this routine in any other way but recursion. If anyone has experience with this sort of thing, could you give me pointers on how to convert the following?

Note: The main routine routine I'm concrened with is "count_distinct_partitions" everything else is non-recursive and just included for reference.

Thanks,

Ken

Code:
static long *gDivisorList = NULL;
static long *gPartitionList = NULL;

// Prototypes
long count_distinct_partitions(long inNum);
long sum_odd_divisors(long inNum);
void init_partition_array(long inMax);
void init_divisor_array(long inMax);


/* ---------------------------------------------------------------- */
/* Counts distinct partitions of a given input number				*/
/* Note: uses global gPartitionList to eliminate unnecessary		*/ 
/* recalculation inside the recursion								*/
/* ---------------------------------------------------------------- */
long count_distinct_partitions(long inNum)
{
	long	result = 0,
			x,
			y,
			i;
			
	for (i = 0; i < inNum; i++)
	{
		x = *(gDivisorList + i);
		
		if ((inNum - i) < 1)
		{
			y = 1;
		}
		else if (*(gPartitionList + inNum - i) != 0)
		{
			y = *(gPartitionList + inNum - i);
		}
		else
		{
			// This is where the problem happens. As inNum gets larger,
			// the recursion gets really deep and causes a stack overflow
			// around inNum = 150
			y = count_distinct_partitions(inNum - i - 1);
			
			*(gPartitionList + inNum - i) = y;
		}
		
		result +=  x * y;
	}
	
	return (result == 0) ? 1 : (result / inNum) ;
}


/* ---------------------------------------------------------------- */
/* Gets the sum of odd divisors for an input number					*/
/* ---------------------------------------------------------------- */
long sum_odd_divisors(long inNum)
{
	// all integers have at least one odd divisor (1)
	// so init result to 1 and start counting from the
	// next odd integer (3)
	long	result = 1,
			i = 3;
			
	while (i < inNum + 1)
	{
		if ((inNum % i) = 0)
			result += i;
			
		i += 2;
	}
	
	return result;
}


/* ---------------------------------------------------------------- */
/* Inits the global partition count array							*/
/* Note: speeds things up considerably inside the					*/ 
/* recursive routines												*/
/* ---------------------------------------------------------------- */
void init_partition_array(long inMax)
{
	long	i;
	
	gPartitionList = (long *) malloc(inMax * sizeof(long));
	
	for (i = 0; i < inMax; i++)
	{
		*(gPartitionList + i) = 0;
	}
}


/* ---------------------------------------------------------------- */
/* Inits the global divisor array									*/
/* Note: speeds things up considerably inside the					*/ 
/* recursive routines												*/
/* ---------------------------------------------------------------- */
void init_divisor_array(long inMax)
{
	long	i;
	
	gDivisorList = (long *) malloc(inMax * sizeof(long));
	
	for (i = 0; i < inMax; i++)
	{
		*(gDivisorList + i) = sum_odd_divisors(i + 1);
	}
}


Reply With Quote
  #2  
Old February 17th, 2004, 01:10 PM
dog135's Avatar
dog135 dog135 is offline
Doggie
Dev Shed Novice (500 - 999 posts)
 
Join Date: Jul 2003
Location: Seattle, WA
Posts: 751 dog135 User rank is Corporal (100 - 500 Reputation Level)dog135 User rank is Corporal (100 - 500 Reputation Level)dog135 User rank is Corporal (100 - 500 Reputation Level)dog135 User rank is Corporal (100 - 500 Reputation Level) 
Time spent in forums: 10 h 38 m 25 sec
Reputation Power: 7
Basically, you put your algorithm into a loop, then store your values on your own stack. If you make the stack out of a linked list, it'll use up as much memory as your computer has before running into a problem. Though it will be a little slower. If your data is all of one type (long) and you know the max number of iterations, then you can store it as an array, and use a counter with it to store your location in the array.
__________________
"Science is constructed of facts as a house is of stones. But a collection of facts is no more a science than a heap of stones is a house." - Henri Poincare

Reply With Quote
  #3  
Old February 17th, 2004, 08:41 PM
ktoz ktoz is offline
Contributing User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Apr 2003
Posts: 473 ktoz User rank is Sergeant Major (2000 - 5000 Reputation Level)ktoz User rank is Sergeant Major (2000 - 5000 Reputation Level)ktoz User rank is Sergeant Major (2000 - 5000 Reputation Level)ktoz User rank is Sergeant Major (2000 - 5000 Reputation Level)ktoz User rank is Sergeant Major (2000 - 5000 Reputation Level)ktoz User rank is Sergeant Major (2000 - 5000 Reputation Level) 
Time spent in forums: 1 Week 3 Days 4 h 51 m 32 sec
Reputation Power: 35
I don't think it's the data that's causing a problem, I think it's the actual routine call. The data size is known before entering the routine but the number of recursions isn't known and for a number like 1000 it might get into the hundreds of thousands if not millions of recursive calls.

I just remembered a stray bit of knowlege from a C book "Enumerate Shell" might be a way to prevent the problem. Off to Google...


Thanks for responding

Ken

Reply With Quote
  #4  
Old March 6th, 2004, 08:41 AM
DaWei_M's Avatar
DaWei_M DaWei_M is offline
Permanently Banned
Dev Shed God 5th Plane (7000 - 7499 posts)
 
Join Date: Jan 2004
Location: Central New York. Texan via Arizona, out of his element!
Posts: 7,351 DaWei_M User rank is Sergeant (500 - 2000 Reputation Level)DaWei_M User rank is Sergeant (500 - 2000 Reputation Level)DaWei_M User rank is Sergeant (500 - 2000 Reputation Level)DaWei_M User rank is Sergeant (500 - 2000 Reputation Level)DaWei_M User rank is Sergeant (500 - 2000 Reputation Level) 
Time spent in forums: 2 Weeks 1 Day 19 h 39 m 7 sec
Warnings Level: 10
Number of bans: 1
Reputation Power: 0
Just imagine that when you reach the recursive call, you exit with the condition that triggered it, rather than making the call, and loop until all such conditions are satisfied.

Reply With Quote
Reply

Viewing: Dev Shed ForumsProgramming Languages - MoreSoftware Design > Converting a recursive algorithm to an iterative one


Thread Tools  Search this Thread 
Search this Thread:

Advanced Search
Display Modes  Rate This Thread 
Rate This Thread:


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
View Your Warnings | New Posts | Latest News | Latest Threads | Shoutbox
Forum Jump


Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
  
 





© 2003-2008 by Developer Shed. All rights reserved. DS Cluster 3 hosted by Hostway
Stay green...Green IT