为什么我的递归调用次数和书上的不一样?
为什么我的递归次数和书上的不一样
根据《算法导论》中钢条切割问题的描述
我按照他的描述,计算了一遍函数调用次数
按理说:
cut_rod(int * p , int n)
当 n = 0 时,cut_rod(p,0) 会直接返回,调用次数为 1。
当 n = 1 时,会调用一次 cut_rod(p, 1),在 cut_rod(p, 1) 内部,还有一次 cut_rod(p, 0),一共调用2 次。
由数学归纳法,可以推导出,调用次数 $$ T(n) = 2^n $$
然而,我运行的结果却是:
下面是我的代码,你能看出是哪里出了问题吗?
#include <stdio.h>
#include <limits.h>
#define N 10
#define max(x, y) ((x)>(y) ? (x) : (y))
unsigned int times = 0;
int cut_rod(int * p, int n);
void main(void)
{
int p[N+1] = {0,1,5,8,9,10,17,17,20,24,30};
int i;
for (i = 0; i <= N; i++)
{
times = 0;
printf("The optimal profit of %d is %3d\n", i, cut_rod(p, i));
printf("function call times: %4d \n", times);
}
}
int cut_rod(int * p, int n)
{
int r;
int i;
times++;
if (n == 0)
return 0;
r = INT_MIN;
for (i = 1; i <= n; i++)
{
r = max(r, p[i] + cut_rod(p, n-i));
}
return r;
}
我用了 gdb 看,愣是没看出问题在哪。
幸好,我还有一个好兄弟,他火眼金睛,一下子就找到问题所在:
问题出现在这里
r = max(r, p[i] + cut_rod(p, n-i));
我调用了一个宏定义函数 max
#define max(x, y) ((x)>(y) ? (x) : (y))
宏定义其实是在预编译阶段将程序中出现的宏替换成宏后面的字符串
max(r, p[i] + cut_rod(p, n-i))
将按照下面的步骤被替换
x 被换成 r, y 被换成 p[i] + cut_rod(p, n-i)
如下图:
于是,替换后的程序就变成了
for (i = 1; i <= n; i++)
{
r = (r) > (p[i] + cut_rod(p, n-i)) ? (r) : (p[i] + cut_rod(p, n-i));
}
这样,我能明显的看出
当 r <= p[i] + cut_rod(p, n-i)
时,cut_rod(p, n-i)
被执行了2次
这样就能解释,GDB调试时,当n = 1时进行到递归调用时,为什么会出现第2次cut_rod()调用了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现