【问题标题】:Proper use of recursion in C在 C 中正确使用递归
【发布时间】:2021-02-23 21:47:56
【问题描述】:

我正在开发一些用于学习目的的基本程序。努力在这种递归函数中找出逻辑。直方图函数中的“循环”如何工作?是否有可能摆脱它并使其仅成为主要功能?任何信息都值得赞赏。 任务是用给定的整数创建水平直方图。

#include <stdio.h>
#include <string.h>
void histogram(int numbers[], int length, int n) {
    int finished = 1;
    for(int i = 0; i < length; i++){

        if(numbers[i] - n > 0)
            finished = 0;}
    if(finished)
        return;
    else {
        histogram(numbers, length, n +1);
        int counter = 0;
        for(int i = 0; i < length; i++) {
            int number = numbers[i] -n;
            if(number > 0)
                printf("* ");
            else
                printf("  ");
        }
        printf("\n");
    }
}
int main(void) {
    int numbers[] = {1, 3, 1};
    int length = sizeof(numbers) / sizeof(int);
    histogram(numbers, length,0);
    return 0;
}

【问题讨论】:

  • 您是否尝试过在纸上或调试器中单步执行程序?
  • histogram 中有 2 个循环。你问的是哪一个?
  • 虽然在 C 中递归调用 main 是合法的,但我建议不要这样做。
  • 理解递归的关键是先理解递归(© koans passim
  • sizeof(numbers) / sizeof(int) 是迈向好代码的好一步。考虑删除所有 type 引用:sizeof numbers / sizeof numbers[0]

标签: c recursion


【解决方案1】:

递归的每次迭代都绘制一条由 * 字符组成的线,即直方图的水平切片。 对于第 n 级,大于或等于 n 的值numbers[i]* 标记,其他值变为空格。 请注意,递归被称为 before 绘制任何东西。因此最深的层次首先被绘制: 例如:

numbers[] = {1, 2, 3, 1}
Level3:  * \n   as  1<3,  2<3, 3>=3,  1<3
Level2: ** \n   as  1<2, 2>=2, 3>=2,  1<2
Level1:****\n   as 1>=1, 2>=1, 3>=1, 1>=1 
Level0:****\n   as 1>=0, 2>=0, 3>=0, 1>=0

这个递归可以重写为两个嵌套循环。

  1. 找到最大高度。设置max_number:
  2. 迭代从 max_number0 的高度。
  3. 对于每个height 遍历整个数组打印*numbers[i] &gt;= height,否则打印

代码:

#include <stdio.h>

void histogram(int numbers[], int length) {
    int max_number = 0;
    for (int i = 0; i < length; ++i)
        if (numbers[i] > max_number)
            max_number = numbers[i];
    for (int height = max_number; height >= 0; --height) {
        for (int i = 0; i < length; ++i)
            if (numbers[i] >= height)
                putchar('*');
            else
                putchar(' ');
        putchar('\n');
    }
}

int main() {
    int A[] = {1,2,3,1};
    histogram(A, 4);
    return 0;
}

产生:

  * 
 ** 
****
****

要制作水平直方图...只需切换循环。

void horiz_histogram(int numbers[], int length) {
    int max_number = 0;
    for (int i = 0; i < length; ++i)
        if (numbers[i] > max_number)
            max_number = numbers[i];
    for (int i = 0; i < length; ++i) {
        for (int height = max_number; height >= 0; --height)
            if (numbers[i] >= height)
                putchar('*');
            else
                putchar(' ');
        putchar('\n');
    }
}

产生:

  **
 ***
****
  **

【讨论】:

    【解决方案2】:

    想象绘制一个表格,其宽度为数字数组的长度,高度为最大值:

    // Pseudocode
    width = length = sizeof(numbers) / sizeof(int) // = 3  
    height = max(numbers[] = {1, 3, 1}) // = 3
    

    histogram() 在每个步骤中检查它是否已到达图表顶部。 如果是这样,它会打印第一行并返回。 否则它会上升一行并再次检查。 这样histogram()首先打印顶行,然后其他“爬下”

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-25
      • 2018-08-09
      • 2017-12-21
      相关资源
      最近更新 更多