递归打印星形图案

Recursively printing a star pattern

对于我的 C++ 数据结构 class 我们的任务是打印这样的星星图案

*
* *
* * *
* * * *
* * * *
* * *
* *
*

模式中的行数由用户输入确定。因此,如果用户输入 4.

,上面的模式就会打印出来

我们之前有一个任务,我们必须打印相反的图案,像这样

* * * * *
* * * *
* * *
* *
*
*
* *
* * *
* * * *
* * * * *

如果用户输入 5,就会打印上面的模式。这个模式,上面那个,我没有问题。我使用 for 循环打印上半部分,然后再次递归调用该函数,然后同样的 for 循环以相反的方向打印下半部分。作为参考,这是我用于上述模式的代码:

int main()
{
    int number;                                             
    cout << "Enter the number of lines in the grid: ";      

    cin >> number;                                          
    printStars(number);                                     
    cout << endl << "Grid Pattern Complete - End of Program.";
    return 0;
} // end of main 

void printStars(int num)                        
{
    if (num < 0) cout << endl << "Please enter a non negative number." << endl;

        else{

            if (num == 0) return;               

            else{
            for (int q = 1; q <= num; q++)      
            {cout << "*";}
            cout << endl;

            printStars(num - 1);        

            for (int q = 1; q <= num; q++)      
            {cout << "*";} 

            cout << endl;
        } 
    } 
} // end printStars

这个函数就像我想要的那样工作,所以我想我会用它作为参考来完成第二个作业。我遇到的问题是,虽然完成第一个任务很容易(打印一行 4 星,然后一行 3,然后一行 2 ,然后一行 1,然后再次打印所有这些逆序),我似乎无法弄清楚如何格式化 for 循环以打印从 1 星行开始的模式,然后是 2 行,然后是 3 行,依此类推,直到它被递归调用并以相反的顺序再次打印。

作为参考,这是我(到目前为止)第二次作业的代码:

int main()
{
    int number;                                             
    cout << "Enter the number of lines in the grid: ";      
    cin >> number;
    printStars(number, 0);                                 

    cout << endl << "Grid Pattern Complete - End of Program.";

    return 0;
}

void printStars(int num, int num2)
{
  if (num2 <= num)
  {

      for (int e = num; e > num2; e--)
      {
          cout << "*";
      }

      cout << endl;

      printStars(num - 1, num2);

  }
}

唯一打印的是模式的后半部分;

(如果用户输入 5)

* * * * *
* * * *
* * *
* *
*

甚至为了完成这项工作,我必须在最后递归调用该函数,这是乱序的。

我想我只是对这个递归应该如何工作感到困惑,但我已经玩了几个小时,我似乎无法重新格式化它、重新排列它或重组它,以便它打印出来我需要它。有人可以给我一些指导吗?也许只是写一些伪代码来帮助我。这是为学校准备的,所以我需要能够理解它,但我现在真的迷路了。

我建议使用两个递归函数,一个按升序打印,另一个按降序打印。

使这两个功能正常运行后,保存该程序的副本。

然后您可以尝试创建一个函数来执行星星的升序和降序。

您在递归调用后没有打印出星星:

void printStars(int num, int num2)
{
  if (num2 < num)
  {

      for (int e = num; e > num2; e--)
      {
          cout << "*";
      }

      cout << endl;

      printStars(num - 1, num2);

      for (int e = num; e > num2; e--)
      {
          cout << "*";
      }

        cout << endl;
  }
}

注意 if 条件也必须稍微改变。我也同意 Thomas 的观点,以不同的方式构建递归可能更有意义:

void printStars(int num)
{
    for (int i = 1; i <= num; i++)
    {
        cout << "*";
    }

    cout << endl;
}

void printStarsRecursive(int stars)
{
    if (stars == 0)
        return;

    printStars(stars);
    printStarsRecursive(stars-1);
    printStars(stars);
}

int main()
{
    int number;                                             
    cout << "Enter the number of lines in the grid: ";      
    cin >> number;
    printStarsRecursive(number);                                 

    cout << endl << "Grid Pattern Complete - End of Program.";

    return 0;
}

如果你想递归地做,你必须记住有多个状态:你数到 N 的状态,以及你倒数到的状态1。所以如果你必须递归地进行,你需要跟踪那些额外的东西:

void printStarsImpl(int count, int initial, int sign)
                    ↑          ↑            ↑
                    current    termination  next step

并且这个函数只需要知道接下来要调用哪个 printStarsImpl() 函数——我们是否只用 count + sign 调用,我们是否将 sign 翻转为 -1,或者我们是否什么都不做...当然是在打印 count * 之后。

那么最初的调用是:

void printStars(int n) {
    printStarsImpl(1, n, +1);
}

试试这个。它是您的代码的最小修改版本。上限传递给所有递归,递归函数调用以 1 开头的值执行(第一行只有 1 开始):

void printStars(int num, int limit)                         
{
        if (num >limit) return;              
        else{
        for (int q = 1; q <= num; q++)      
        {cout << "*";}
        cout << endl;

        printStars(num +1, limit);        

        for (int q = 1; q <= num; q++)      
        {cout << "*";} 

        cout << endl;
    } 

}

int main()
{        
    int number=5;  
    cin>>number;                                
    printStars(1, number);                                     

    return 0;
} // end of main 

我测试了一下,结果是正确的。 link 是:

http://ideone.com/ez6pZ5

ideone 结果:

Success time: 0 memory: 3144 signal:0

*
**
***
****
*****
*****
****
***
**
*

如果使用声明为只有一个参数的函数,最直接的方法是在函数中使用静态局部变量

#include <iostream>

void print_stars( size_t n )
{
    static size_t m;

    if ( m++ != n )
    {
        for ( size_t i = 0; i < m; i++ ) std::cout << '*';
        std::cout << std::endl;
        print_stars( n );
    }

    --m;
    for ( size_t i = 0; i < m; i++ ) std::cout << '*';
    std::cout << std::endl;
}

int main() 
{
    while ( true )
    {
        std::cout << "Enter a non-negative number (0-exit): ";

        size_t n = 0;
        std::cin >> n;

        if ( !n ) break;

        std::cout << std::endl;
        print_stars( n );
        std::cout << std::endl;
    }

    return 0;
}

程序输出看起来像

Enter a non-negative number (0-exit): 4

*
**
***
****
****
***
**
*


Enter a non-negative number (0-exit): 3

*
**
***
***
**
*


Enter a non-negative number (0-exit): 2

*
**
**
*


Enter a non-negative number (0-exit): 1

*
*


Enter a non-negative number (0-exit): 0

如果您不想在递归函数中使用静态变量,那么您可以使用标准流成员函数 width 来代替它。在这种情况下,递归函数将如下所示

#include <iostream>
#include <iomanip>

void print_stars( size_t n )
{
    std::streamsize m = std::cout.width();

    if ( m++ != n )
    {
        std::cout.width( m );
        std::cout << std::setfill( '*' );
        std::cout << '*' << std::endl;
        std::cout.width( m );
        print_stars( n );
    }

    std::cout.width( m-- );
    std::cout << std::setfill( '*' );
    std::cout << '\n';
}

int main() 
{
    while ( true )
    {
        std::cout << "Enter a non-negative number (0-exit): ";

        size_t n = 0;
        std::cin >> n;

        if ( !n ) break;

        std::cout << std::endl;
        print_stars( n );
        std::cout << std::endl;
    }

    return 0;
}

输出与上面相同。

P.S。看来能写出功能的程序员只有我失业了。:) 其他人都做不了这个初学者的作业。:)

为了练习 - 打印星星的递归函数和确定星星数量的递归函数如何:

string ReturnStars(int number)
{
  if (number > 1)
    return "*" + ReturnStars(number -1);

  return "*";
}

void PrintStars(int start, int lines)
{
  cout << ReturnStars(start) << endl;

  if (start < lines)
    PrintStars(start + 1, lines);

  cout << ReturnStars(start) << endl;
}

int main()
{
  int numberLines = 1;
  cout << "Please enter a positive number to print a star pattern for: ";
  cin >> numberLines;
  PrintStars(1, numberLines);

  return 0;
}

输出示例:

我认为最佳答案应该是如果只使用一个递归函数 -

#include <iostream>

using namespace std;

void recursive(int current, int lastEnter, int limit, bool isLimitReached) {
    cout << "*";
    if(current == lastEnter ) {
        cout << endl;
        current = 0;
        if(isLimitReached == false) 
            lastEnter++;
        else lastEnter--;
    }
    if(current + 1 == limit) {
        isLimitReached = true;
    }
    current++;
    if(!(isLimitReached == true && lastEnter == 0))
        recursive(current, lastEnter, limit, isLimitReached);
}

int main()
{
    int num = 0;
    cout << "Enter max number of stars to be generated : ";
    cin >> num;
    recursive(1, 1, num, false);
    return 0;
}

上面的代码只使用了一个没有for/while循环的递归函数。 输出-

Enter max number of stars to be generated : 6 
*  
**       
***    
****    
*****   
******  
*****     
****    
***    
**   
*