简体   繁体   English

C++中的帕斯卡三角形

[英]Pascal's triangle in C++

I'm trying to make a Pascal triangle in C++.我正在尝试用 C++ 制作一个帕斯卡三角形。 But I couldn't do that!但我做不到! What's wrong with my code?我的代码有什么问题?

#include <iostream>
using namespace std;

 int main()
 {
    int rows = 5;
    int currentNumber = 1;
    int numbers;
    int tempNumber;
    bool odd;

    for(int i = 0; i < rows; i++)
    {
        numbers = i+1;
        if(i%2 != 0) {
            odd = true;
        } else {
            odd = false;
        }
        for(int j = 0; j < (rows/2)-(numbers/2); j++)
        {
            cout << "  ";
        }
        if(odd)
        {
            cout << " ";
        }

        currentNumber = 1;
        tempNumber = 0;
        for(int k = 0; k < numbers; k++)
        {
            cout << currentNumber << " ";

            if(k > numbers/2) {
                currentNumber-=tempNumber;
                tempNumber-=currentNumber;
            } else {
                currentNumber+=tempNumber;
                tempNumber+=currentNumber;
            }
        }
        cout << endl;
    }

    cout << "test";
 }

And the output is below:输出如下:

    1 
   1 1 
  1 1 2 
 1 1 2 5 
1 1 2 5 -3 
test

The first thing I would do is not worry about the actual arrangement of the numbers when they're printed.我要做的第一件事是不用担心数字在打印时的实际排列。 This is a similar concept across all of programming, you want to separate the concern of how things are displayed, the "view" from how things are in data, the "model".这是所有编程中的一个相似概念,您希望将事物如何显示、“视图”与事物在数据中的形式、“模型”分开。 Now that you have a conceptual basis for structuring the code, I would also use class structures and objects, since you say that C++ is what you're trying to practice, which is mainly focused around the object-oriented programming (OOP) paradigm.既然您已经有了构建代码的概念基础,我还将使用类结构和对象,因为您说 C++ 是您要练习的内容,它主要集中在面向对象编程 (OOP) 范式上。 With these ideas in place we can begin to come up with a way for how we want to create the triangle.有了这些想法,我们就可以开始想出一种方法来创建三角形。

What we want to achieve is the procedural production of the following structure:我们要实现的是以下结构的程序化生产:

     1
    1 1
   1 2 1
  1 3 3 1
 1 4 6 4 1

to achieve this affect we really want to create:为了达到这种效果,我们真正想要创造:

1
1,1
1,2,1
1,3,3,1
1,4,6,4,1

If you notice from the above diagrams, we can deduce that starting with the axiom (the very first iteration/something assumed to be there before we even start) which in this case is simply a row containing only the number 1 , we can see that each production (any given iteration, which has some rule to produce it, starting first with the axiom, 1 ) is given by adding the two values in the row above it, that have the same index, and the next index.如果您从上图中注意到,我们可以从公理(第一次迭代/甚至在我们开始之前假设存在的东西)开始推断,在这种情况下,它只是仅包含数字1的一行,我们可以看到每个产生式(任何给定的迭代,它有一些规则来产生它,首先从公理开始, 1 )通过将其上方行中的两个值相加得到,这些值具有相同的索引,以及下一个索引。 For the sake of the algorithm we're going to assume that if the production can't find a number we'll say that the number exists but isn't shown, and we'll assume that it's 0. (if it's all the way on the left side, there's no first value, and if it's all the way on the right side there's no second value)为了算法的缘故,我们将假设如果产生式找不到一个数字,我们会说这个数字存在但没有显示,我们会​​假设它是 0。(如果它是所有的在左侧,没有第一个值,如果一直在右侧,则没有第二个值)

So that means if you look at my second diagram, we have the first row which is just 1 but we're going to pretend that it's really 0,1,0 .所以这意味着如果你看我的第二张图,我们的第一行只有1但我们将假装它真的是0,1,0 That gives us a pyramid more like:这给了我们一个更像金字塔:

0,1,0
0,1,1,0
0,1,2,1,0
0,1,3,3,1,0
0,1,4,6,4,1,0

The most important part is the axiom 1 which we'll assume to be 0,1,0 .最重要的部分是公理1 ,我们假设它是0,1,0 Now let's figure out the code for our "production" that is, the method to create a row, given the row before it.现在让我们弄清楚我们的“生产”的代码,即在给定行之前创建一行的方法。 We want to make a function that will take a list of numbers from the previous row, and create the next row, assuming that it's padded with our 0 s on either side.我们想要创建一个函数,它将从前一行中获取一个数字列表,并创建下一行,假设它在每一侧都用我们的0填充。 That function might look something like this:该函数可能如下所示:

std::vector<int> produceNextRow(std::vector<int> previousRow) {
  std::vector<int> nextRow;

  int left, right = 0;
  /* For each of the numbers in the previous row, plus one more
  because each next row has one more value than the last */
  for( int i = 0; i < previousRow.size()+1 ; i++ ) {
    
    // If we're all the way on the left we need 'left' to be our imaginary 0
    if( i == 0 ) {
      left = 0;
    } else {
      /* Otherwise we want it to be the value in the same position of the
      previous row which is slightly to the left, hence -1 */
      left = previousRow[i-1];
    }

    // If we're all the way on the right, we need 'right' to be our imaginary 0
    if( i == previousRow.size() ) {
      right = 0;
    } else {
     /* Otherwise we want it to be the value of the previous row, at the same
      position */
      right = previousRow[i];
    }

    /* Finally we add left and right, to get our new number, then we put it into
    the next row */
    nextRow.push_back(left+right);
  }

  // Let's return our new row we created
  return nextRow;
}

In reality this is all we need.事实上,这就是我们所需要的。 Now you simply need to use a trick to put spaces in between them and print them out.现在你只需要使用一个技巧在它们之间放置空格并将它们打印出来。 I won't do that here, but I'll show you how to use this function to produce a few rows of the triangle:我不会在这里这样做,但我会向您展示如何使用此函数来生成三角形的几行:

int main(int argc, char *argv[]) {

  // Vector of vectors of ints! This is our entire triangle
  std::vector<std::vector<int>> triangle;
  std::vector<int> axiom {1};

  // Lets put our axiom into the triangle first
  triangle.push_back(axiom);

  // Alright, for the sake of example lets do some number of productions like 6
  int productions = 6;
  for( int i=0; i < productions ; i++ ) {
    triangle.push_back(produceNextRow(triangle[i]));
  }

  /* Now lets print out our triangle, you'd replace this with something fancy
  that maybe computes how many spaces are required, and makes the triangle look
  better. I'll leave that as an exercise for you */

  // For each row in the triangle
  for( int i=0; i < triangle.size() ; i++ ) {
    // For each number in the row
    for( int j=0; j < triangle[i].size() ; j++ ) {
      // print that number followed by a comma and a space
      std::cout << triangle[i][j] << ", ";
    }
    // print a new line after each row
    std::cout << std::endl;
  }

  return 0;
}

I've left putting this into a class object, and also pretty printing it like an actual pascal triangle as exercises for you, I think you should try it out, and spend time really thinking about what's going on in the produceNextRow method.我已经把它放到一个类对象中,并且还把它打印成一个实际的帕斯卡三角形作为练习,我认为你应该尝试一下,花时间真正思考一下produceNextRow方法中发生了produceNextRow

If you imagine your triangle as left-justified ( https://en.wikipedia.org/wiki/Pascal%27s_triangle#Overall_patterns_and_properties ) then it can be presented as 2d array:如果您将三角形想象为左对齐( https://en.wikipedia.org/wiki/Pascal%27s_triangle#Overall_patterns_and_properties ),那么它可以表示为二维数组:

#include <iomanip> //setw
....

    static int const size = 20;
    int const width = 6;
    int cell[size][size+1];

    for (int i = 0; i < size; ++i)
    {
        cell[i][0] = 1;
        cell[i][i + 1] = 0;

        std::cout << std::string((size - i) * width / 2, 0x20) << cell[i][0];

        for (int j = 1; j <= i; ++j)
        {
            cell[i][j] = cell[i - 1][j - 1] + cell[i - 1][j];
            std::cout << std::setw(width) << cell[i][j];
        }

        std::cout << std::endl;
    }

Prints:打印:

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM