我已经开始练习一些C并找到了这个很好的练习,我必须通过输入打印一个三角形。 对于输入6,它将打印
*
**
***
****
*****
******
*****
****
***
**
*
现在,看着它,我想,嗯,这不是一项艰巨的任务。所以我决定尝试使用递归,没有循环和只有2个变量来编写它。 该函数应如下所示:
void PrintTriangle(int iMainNumber, int iCurrNumber)
{
//Logic goes here
}
几个小时后,我意识到这比我想象的要困难得多,因为我需要为函数传递足够的信息,以便能够“记住”应该打印多少个三角形。
所以现在我决定问你是否可能。
(记住,没有循环,没有其他功能,只有递归)。
修改 这不是功课,这纯粹是出于好奇心。但是我可能无法为您验证。 我已经成功地完成了这个
void PrintTriangle(int iMainNumber, int iCurrNumber)
{
if (iMainNumber == 0)
{
printf("\r\n");
}
else if (iMainNumber == iCurrNumber)
{
printf("\r\n");
PrintTriangle(iMainNumber - 1, 0);
}
else
{
printf("%s", MYCHAR);
PrintTriangle(iMainNumber, iCurrNumber + 1);
}
}
我试图创建相反的函数时遇到困难,我相信如果我能做到这一点,我将能够使用iMainNumber和iCurrNumber在函数流中导航的正面或负面的事实。
换句话说,当参数为负时,我会在输入长度减去1时打印一颗降星,当参数为正时,我会在输入长度中打印升序星。
我考虑过使用标志,但不是2个整数。
也许如果我添加另一个标志并且有2个整数和一个标志然后我可以解决它,但正如我所说,我试图将自己限制为2个整数。
我开始想到的是,如果不使用超过2个整数和递归,就无法传递在此方法中打印升序星所需的信息。
但我仍然不太确定,因此问题。
答案 0 :(得分:3)
使用相同数量的变量进行递归可以完成循环。您只需要弄清楚状态是什么,并在递归调用中传递更新状态,而不是循环。
首先让我们迭代一次。输入为size
,即三角形的大小。我们有两个状态变量,{1}从1到lineNumber
,size*2-1
从1到columnNumber
。请注意:
size
迭代版本将是这样的:
columnsForLine = lineNumber <= size ? lineNumber : size*2 - lineNumber
那does indeed work。现在如何递归?只是弄清楚状态正在更新的地方,并将其作为递归调用:
int lineNumber = 1;
int columnNumber = 1;
int size = 6;
while (lineNumber <= size*2-1) {
printf("*");
int columnsForLine = lineNumber <= size ? lineNumber : size*2 - lineNumber;
if (columnNumber == columnsForLine) {
printf("\n");
columnNumber = 1;
lineNumber += 1;
}
else {
columnNumber += 1;
}
}
请注意,代码基本相同,只是以不同方式执行控制流程。另请注意,这是尾递归的,这意味着智能编译器可以执行递归调用而不会为每次调用增加堆栈。
嗯,如果你只想使用2个变量,包括输入,将会有点棘手...你总是可以欺骗并将所有3个整数填充到一个整数中,然后解压缩它每次重新包装。 e.g。
void recstars(int size, int lineNumber, int columnNumber) {
if (!(lineNumber <= size*2 - 1)) {
return;
}
printf("*");
int columnsForLine = lineNumber <= size ? lineNumber : size*2 - lineNumber;
if (columnNumber == columnsForLine) {
printf("\n");
recstars(size, lineNumber + 1, 1);
}
else {
recstars(size, lineNumber, columnNumber + 1);
}
}
recstars(6, 1, 1);
Seems to work。你认为那是合法的吗?
否则,棘手的部分不是递归,它只是通过状态只有2个整数来完成工作。你能用2个整数迭代地做吗?
答案 1 :(得分:3)
我想出了:
void PrintTriangle(int size, int indent)
{
switch(size) {
case 0:
if (indent > 1) PrintTriangle(size, indent-1);
putchar('*');
break;
case 1:
PrintTriangle(size-1, indent+1);
putchar('\n');
break;
default:
PrintTriangle(1, indent);
PrintTriangle(size-1, indent+1);
PrintTriangle(1, indent);
break; }
}
int main()
{
PrintTriangle(6, 0);
return 0;
}
作为快速的第一次尝试。似乎可以完成这项工作。
size
是要打印的三角形的大小,indent
是在三角形的每一行之前打印的额外星星的数量。 size==0
表示只打印indent
个星号,没有换行符(用于在三角形之前打印缩进)
如果你想要更紧凑的东西,可以将其重写为:
void PrintTriangle(int size, int indent)
{
if (size <= 0) {
if (indent > 1) PrintTriangle(size, indent-1);
putchar('*');
} else {
if (size > 1) PrintTriangle(1, indent);
PrintTriangle(size-1, indent+1);
if (size > 1) PrintTriangle(1, indent);
else putchar('\n'); }
}
答案 2 :(得分:1)
使用2个参数作为OP建议
void PrintTriangle(int iMainNumber, int iCurrNumber) {
if (iMainNumber < 0) { // Row (use negative iMainNumber)
printf("%c", '*');
PrintTriangle(iMainNumber + 1, 0);
if (iMainNumber == -1)
printf("\n");
} else if (iMainNumber > 0) {
if (iCurrNumber < iMainNumber) { // Preceding short lines
if (iCurrNumber > 1)
PrintTriangle(iMainNumber, iCurrNumber - 1);
PrintTriangle(-iCurrNumber, 0);
} else if (iCurrNumber == iMainNumber) {
PrintTriangle(iMainNumber, iCurrNumber - 1); // left
PrintTriangle(iMainNumber, iCurrNumber + 1); // Right
} else { // Subsequent short lines
if ((iCurrNumber - iMainNumber) < iMainNumber)
PrintTriangle(iMainNumber, iCurrNumber + 1);
PrintTriangle(-(iCurrNumber - iMainNumber), 0);
}
}
}
int main() {
PrintTriangle(3,3);
PrintTriangle(6,6);
return 0;
}
答案 3 :(得分:0)
根据我的阅读,大多数建议已经指出要传递你需要的任何状态。
但是,你真的不需要那么多的分支语句。您需要的大部分内容都可以通过算术得出。您可以计算递归总数,并从当前递归计数中获取星数。此外,通过将初始调用的部分与递归分开,可以使使用更加简单。
刚看到你不想要两个以上的整数。考虑下面的内容,看看你是否真的想保持这种偏好。如果是这样,您可以在递归部分中计算总计。我认为它的可读性会降低。
void _print_stars(int height, int total, int current)
{
int stars = current <= height ? current : 2 * height - current;
for (int i = 0; i < stars; i++) { printf("*"); }
printf("\n");
if (current != total)
{
_print_stars(height, total, current + 1);
}
}
void print_stars(int height)
{
int total_recursions = 2 * height - 1;
_print_stars(height, total_recursions, 1);
}
答案 4 :(得分:0)
纯递归,没有循环,调用程序'main()'只传递一个参数:
void PrintTheClms(int width, int stars) {
printf("*");
if stars < width then {
PrintTheClms(width, stars+1);
}
}
void PrintStars(int width) {
PrintTheClms(width, 1);
printf("\n");
}
void PrintTheRows(int size, int indent) {
PrintStars(indent);
if indent < size then {
PrintTheRows(size, indent+1);
PrintStars(indent);
}
}
void PrintTriangle(int size) {
if size > 0 then {
PrintTheRows(size, 1);
}
}
int main() {
PrintTriangle(6);
PrintTriangle(11);
// etc.
return 0;
}
非常简单 - 没有else子句,没有case构造,没有方向标志。但是,很多过程和很多电话。