C语言递归函数调试问题:递归无法终止及return与return 0区别咨询
问题分析与解决方案
核心问题拆解
1. 递归重复输出、无法终止的原因
你的代码递归逻辑存在两个关键问题:
- 在
if(third == n - 1)分支调用递归后,没有添加return语句,导致调用完这个递归后,会继续执行下面的BlackJack(first, second + 1, third + 1, n, m),产生大量多余的递归分支。 - 即使触发
first == n - 3的return 0,也只是终止当前的递归栈帧,上层未完成的递归仍会继续执行,因此会重复输出结果。 - 全局变量的使用也会导致不同递归分支之间的状态混乱,进一步加剧问题。
2. return; 和 return 0; 的区别
针对C语言的函数返回规则:
- 当函数返回值类型为
int(比如你的BlackJack函数):return 0;:终止当前函数执行,同时向调用者返回整数值0,是符合语法的正确写法。return;:属于未定义行为,编译器可能报错或返回随机值,但同样会终止当前函数。
- 当函数返回值类型为
void时,只能用return;来终止函数,不能带返回值。
代码修正方案
修正后的递归版本
调整递归终止逻辑,移除全局变量,避免状态污染:
#include <stdio.h> #include <stdlib.h> static int cards[100]; // 用指针传递最优解,避免全局变量干扰 void BlackJack(int first, int second, int third, int n, int m, int *best_sum) { // 遍历当前first、second与所有>=third的卡片组合,更新最优解 for(int i = third; i < n; i++){ int sum = cards[first] + cards[second] + cards[i]; if(sum <= m && sum > *best_sum){ *best_sum = sum; } } // 终止条件:所有组合遍历完成 if(first == n - 3){ return; } // third到达末尾时,切换到下一组first、second,重置third if(third == n){ BlackJack(first + 1, first + 2, first + 3, n, m, best_sum); return; // 调用后直接返回,避免触发后续递归 } // 遍历下一组second、third的组合 BlackJack(first, second + 1, third + 1, n, m, best_sum); } int main(){ int n = 0, m = 0; int best_sum = 0; scanf("%d %d", &n, &m); for(int i = 0; i < n; i++){ scanf("%d", &cards[i]); } BlackJack(0, 1, 2, n, m, &best_sum); printf("%d\n", best_sum); return 0; }
更直观的非递归实现
用三重循环直接遍历所有合法组合,逻辑清晰不易出错:
#include <stdio.h> int main(){ int n, m; scanf("%d %d", &n, &m); int cards[100]; for(int i = 0; i < n; i++){ scanf("%d", &cards[i]); } int best = 0; // 遍历所有i<j<k的三元组组合 for(int i = 0; i < n; i++){ for(int j = i+1; j < n; j++){ for(int k = j+1; k < n; k++){ int sum = cards[i] + cards[j] + cards[k]; if(sum <= m && sum > best){ best = sum; } } } } printf("%d\n", best); return 0; }
内容的提问来源于stack exchange,提问作者albert3289
相关产品推荐
相关产品推荐

