写一个简单的数字三角形的建议,只有递归,没有循环?

时间:2013-10-10 18:39:23

标签: c++ recursion

所以我已经编写了一个函数来使用几个for循环来编写一个可变高度的数字金字塔,它可以很好地工作。

以下是我正在谈论的那种金字塔的例子:

用户进入4

      1 

    1 2 1

  1 2 3 2 1 

1 2 3 4 3 2 1 

所以我确实需要用空格填充左侧。

我的问题是我无法使用仅递归,没有循环。我甚至无法想到一个在递归方面的起点,真的。我知道我需要一个基本案例,以及一种接近基本案例的方法。

我应该编写多个递归函数,还是有办法只用一个? (除了主要,我的意思是。)

这是我到目前为止所做的事情(它根本不多):

void givepyramid(int lines);  //lines = Number of lines in pyramid (4 in example above)
{
     if lines == 1;
        cout << (//all the spaces needed)<<1;
     else
         cout << (I'm not too sure on how to go about this here.)
}

任何建议都将不胜感激!感谢。

7 个答案:

答案 0 :(得分:2)

这是一个简单的解决方案,可以在不使用循环的情况下绘制漂亮的三角形:

#include <iostream>

void printRowNumbers( unsigned int n, unsigned int max )
{
    if ( n < max ) {
        std::cout << n << ' ';
        printRowNumbers( n + 1, max );
    }
    std::cout << n << ' ';
}

void drawTriangle( unsigned int n, unsigned int indent = 0 )
{
    if ( n > 1 ) {
        drawTriangle( n - 1, indent + 2 );
    }
    std::cout << std::string( indent, ' ' );
    printRowNumbers( 1, n );
    std::cout << "\n";
}

主要的想法是,你通常使用循环来解决两个问题:

  1. 打印一行数字(没有任何特定缩进),例如1 2 3 2 11 2 3 4 5 4 3 2 1。关键的想法是,您不仅要将数字打印到最大值并且返回,您实际上是从一些起始值(这里似乎总是1)打印数字到最大值,然后回到起始值。

    深刻的是,从1到5打印这样的“数字镜像”并且返回与打印1相同,然后从2到5打印镜像,然后再打印1。从2到5打印镜像与打印2相同,然后从3到5进行镜像,然后再打印2。等等,直到最小值与最大值相同,在这种情况下,您只需打印该数字(这是您的基本情况)。

  2. 多次打印内容,每次都在新行上缩进。我们需要一个能够多次打印某些东西(比如一个字母)的功能 - 每一次,都是按照自己的路线和不断减少的缩进。最后一行根本没有缩进。简单的情况是只打印一行 - 在这种情况下,您根本没有任何缩进。打印两行与首先打印一行并使用缩进(例如2)相同,然后再次打印该行。打印三行意味着首先打印两行,缩进为2(这意味着打印一行,缩进为4!),然后第三行没有缩进。

    我们的代码恰好不打印一些随机字母,而drawTriangle函数负责缩进(并打印换行符),但让printRowNumbers打印实际数字。

  3. 正如您所看到的,我没有使用非常好的分析方法(可以将任何循环重写为递归,因此您可以编写一个循环,然后通过遵循一些规则将其机械转换为递归)。相反,我只是手工做了一些实验,比如“做两次这样的做法与做一次有什么不同,怎么做三次与做两次不同”然后发现一个模式。

答案 1 :(得分:0)

我没有测试过这段代码,但你可以做这样的事情。它不使用任何循环。这将打印出一个倒金字塔,所以我将把不可逆的部分留给读者练习。

void givepyramid(int lines)
{
    giveIndentedPyramid(lines, 0);
}

void giveIndentedPyramid(int line, int indentation)
{
    printIndentationRecursive(indentation);

    if(line > 0)
    {
        printLineRecursiveUp(1, line);
        printLineRecursiveDown(line);

        cout << endl;
        giveIndentedPyramid(line-1, indentation+2);
    }
}

void printIndentationRecursive(int indentation)
{
    /*
    for(int i = 0; i < indentation; i++)
    {
        cout << " ";
    }
    */
    if(indentation > 0)
    {
        cout << " ";
        printIndentationRecursive(indentation-1);
    }
}

void printLineRecursiveUp(int current, int line)
{
    /*
    for(int i = 1; i < line; i++)
    {
        cout << i << " ";
    }
    */
    if(current < line)
    {
        cout << current << " ";
        printLineRecursiveUp(current + 1, line);
    }
}

void printLineRecursiveDown(int line)
{
    if(line > 0)
    {
        cout << line << " ";
        printLineRecursiveDown(current - 1, line);
    }
}

请记住,这是未经测试的代码,因此请将其视为伪代码,您可以将其用作学习如何使用递归的指南。

答案 2 :(得分:0)

适用于数字&gt; 10,完全没有循环。

PS:C ++ 11

#include <iostream>
#include <vector>
#include <string>


void gen_numbers(int len, int number, std::string &ans) {

    if (len > 1) {
        ans.append(std::to_string(number));
        ans.push_back(' ');
        gen_numbers(len - 1, number + 1, ans);
        ans.push_back(' ');
        ans.append(std::to_string(number));
    }
    if (len == 1)
        ans.append(std::to_string(number));

}

void print_spaces(int number) {
    std::cout << " ";
    if (number)
        print_spaces(number - 1);
}

void draw (int line, int depth) {
    if (line > 1) {
        draw(line - 1, depth);
    }

    print_spaces(2 * (depth - line));
    std::string ans;
    gen_numbers(line, 1, ans);
    std::cout << ans;
    print_spaces(depth - line);
    std::cout << std::endl;
}



int main() {
    draw(12, 12);
    return 0;
}

答案 3 :(得分:0)

我创建了以下解决方案。 它适用于更多行数。

#include <iostream>
#include <vector> 
using namespace std;

void buildLine(int countline, int iteration)
{
 cout << string((countline-iteration),'\t');


 for(int i = 0; i < iteration; ++i)
 {
  cout << i+1 << "\t";
 }

 for(int i = iteration-1; i > 0; --i)
 {
   cout << i << "\t";
 }

 cout << string(countline-iteration,'\t') << endl;

 buildLine(countline,++iteration);

}

void buildPyramid(int lines)
{
 buildLine(lines, 1);
}


int main() {

   buildPyramid(11); 
}

enter image description here

答案 4 :(得分:0)

您可以使用两个不同的递归函数,这些函数可能会也可能不会简化为单个递归函数。可以编辑下面的示例以相对简单地填充左侧,并将其保留为练习。基本上,你想分别在左边和右边构建字符串的行,然后围绕中心数加入它们。

std::string buildString(int i, bool side)
{
    if(i < 1)
    {
        return "";
    }
    if(i == 1)
    {
        return "1";
    }
    if(i > 1)
    {
        std::ostringstream s;
        s << i;
        if(side == false) // left build
        {
             return buildString(i - 1, false) + " " + s.str();
        }
        if(side == true) // right build
        {
             return s.str() + " " + BuildString(i - 1, true);
        }
     }
 }

 //pass is function the expected length as well in order to enable padding
 void buildPyramid(int i /*, int max */)
 {
     if(i < 1)
     {
          return;
     }
     if(i > 1)
     {
          //by calling build pyramid recursively and falling through to the print statement after, you can cause the top of the pyramid to print first without looping
          buildPyramid(i - 1);
     }
     //the center number of each row is added here since it's the only number that isn't duplicated. By storing the resultant string in an ostringstream you can check the length and add padding.
     std::cout << buildString(i - 1, false) << " " << i << " " << buildString(i - 1, true);
 }

答案 5 :(得分:0)

没有循环的简单递归函数:

void printTree(int maxLevel, int currLevel = 0, int currPos = 1)
{
    if(currLevel>maxLevel)
        return;
    if(currPos<(maxLevel-currLevel))
    {
        cout<<'\t';
        printTree(maxLevel, currLevel, ++currPos);
    }
    else if(currPos<(maxLevel-currLevel + currLevel*2)-1)
    {
        cout<<((maxLevel - currPos)<=0?(currPos - maxLevel)+2:(maxLevel - currPos))<<'\t';
        printTree(maxLevel, currLevel, ++currPos);
    }
    else
    {
        cout<<endl;
        printTree(maxLevel, ++currLevel, 0);
    }
}

对于您的示例,请将该函数调用为printTree(4)

答案 6 :(得分:0)

您可以替换

for (int i = 0; i != N; ++i) {
    body(i, localVars);
}

通过

void body_rec(int N, int i, LocalVars& localVars)
{
    if (i == N) return;
    body(i, localvars);
    body_rec(N, i + 1, localVars)
}