我开始自学C并且正在尝试构建一组有用的功能和程序以供将来参考。如果相关,这是C99。
这是我最近的程序迭代。在输出中,我想得到数n的素因子化。但是,我会得到所有因素的列表,并且不会重复任何因素。我包含了一些打印语句来尝试和调试,并且发现错误与递归有关,但无法弄清楚如何进一步解释它。我之前尝试过使用int类型的递归函数,但很难让它使用数组p。
我知道可能有更有效的方法来声明p来节省内存,但由于这主要是供参考,因此内存不是一个大问题。
我发现了这些问题,但并不认为他们回答了我的问题
我的主要问题是: 为什么输出显示n的所有因子? 为什么不重复主要因素? 我该怎么做才能解决它?
Stream
答案 0 :(得分:0)
来自This answer:
why does recursion cause stackoverflow so much more than loops do
因为每次递归调用都会在堆栈上使用一些空间。如果递归太深,那么它将导致StackOverflow,具体取决于堆栈中允许的最大深度。
使用递归时,您应该非常小心,并确保提供基本案例。递归中的基本情况是递归结束的条件,堆栈开始展开。这是导致StackOverflow错误的递归的主要原因。如果它没有找到任何基本情况,它将进入无限递归,这肯定会导致错误,因为Stack只是有限的。
-
看来你的for阻碍了,c会增加,并且不会再次检查相同的值。
例如,如果输入为8,我们需要(2,2,2)
而不是(2,4)
。
我建议暂时替换你的if (c%n ==0)
,不要忘记在那个时候替换n的值,你不想在那里循环。
这似乎是一个很好的答案:
int primes(int nbr, int cur)
{
if (cur > nbr)
return (0);
else
{
if (nbr % cur == 0 && isprime(cur) == 1)
{
printf("%d\n", cur);
return (primes(nbr / cur, 2));
}
return (primes(nbr, cur + 1));
}
}
在主
中使用cur = 2调用该函数答案 1 :(得分:0)
编辑我发现n的最小因子保证是素数,所以我已经相应地编辑了答案。
为什么输出显示n的所有因子?
因为您测试c是否是n的因子并将其添加到数组p中c是否为素数。然后你继续测试c以上的数字,甚至是c的倍数。
为什么不重复主要因素?
因为当你发现数字c是一个因素时,你不必检查它以确定它本身是否为复合数。
将c添加到p后,您需要在factor
上递归调用(n / c)
,然后停止。
这大致是你需要的(但未测试甚至编译)
int factorise(int n, int p[], int j)
{
int factorsFound = 0;
for (c = 2 ; c * c <= n && factorsFound == 0 ; ++ c)
{
if (n % c == 0)
{
p[j] = c;
factorsFound = factorise(n / c, p, j + 1) + 1;
}
}
if (factorsFound == 0) // n is prime
{
p[j] = n;
factorsFound = 1;
}
return factorsFound;
}
同样在真正的解决方案中,您可能希望传递p的大小,以便您可以检测是否空间不足。
只是为了好玩,因为还没有其他人发布它,这是一个非递归的解决方案。它实际上与上面相同,但递归已转换为循环。
int factorise(int number, int p[])
{
int j = 0;
for (int c = 2, int n = number ; n > 1 ; )
{
if (n % c = 0)
{
p[j++] = c;
n = n / c;
}
else
{
c++;
}
}
return j;
}
我不同意Lundin关于递归的一些评论。递归是将问题分解为更容易的子任务的一种自然方式,但在C中,它无可否认效率较低,尤其是在堆栈空间方面,在这种特殊情况下,非递归版本更简单。
答案 2 :(得分:0)
你已经在评论中告诉你这个算法很差,这是一个证据。你真的应该学会使用调试器:通过调试器运行它会立即显示问题所在。
话虽这么说,你的主要问题是当递归函数返回时该做什么?。你没有问自己这个问题在递归中是必须的,只是按顺序继续,这是完全错误的,因为你将重用已经在递归调用中处理过的数字。所以你必须在递归调用factors
之后立即添加一个返回行。
一旦完成,还有另一个小问题(调试器会显而易见),你只搜索严重小于n
的因子。所以你错过了最后一个主要因素......
通过这两个即时修复,您的代码变为:
void factors(int n, int p[], int j) {
/// if n is divisible by c, store c, and continue with n/c
int c;
for (c=2; c <= n; c++) {
if (c > n) break;
if (n%c == 0) {
p[j] = c;
printf("%d has been added to p \t", c);
printf("n has been reduced to %d \t", n/c);
printf("j is %d \n", j);
j++;
if (n == c) break;
factors(n/c, p, j);
return;
}
}
}
但恕我直言p[j] = c;
应成为*p = c;
而factors(n/c, p, j);
应成为factors(n/c, p+1, j);
。换句话说,您直接传递指向下一个插槽的指针。