
February 15th, 2004, 12:55 AM
|
|
|
|
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);
}
}
|