打印出右图10行的杨辉三角。

提示:找规律: 第一行、第二行元素都是1; 第n行的元素个数也为n; 每一行第一个元素和最后一个元素为1; 其他元素为上一行两个元素之和,如a[i][j]=a[i-1][j]+a[i-1][j-1].

#include <stdio.h>

int main()
{
    int n;
    scanf("%d",&n);
    printf("\n");
    int a[n][n] = {0};
    
    for (int i = 0; i < n; i++) 
    {
        a[i][0] = 1;
        a[i][i] = 1;
        for (int j = 1; j < i; j++) 
        {
            a[i][j] = a[i-1][j-1] + a[i-1][j];
        }
    }

    for (int i = 0; i < n; i++) 
    {
        for (int j = 0; j <= i; j++) 
        {
            printf("%d ", a[i][j]);
        }
        printf("\n");
    }

    return 0;
}

我们把这段代码放到显微镜下,一行一行地“解剖”开来。这次我们不只要看懂它在做什么,还要弄懂它为什么这么做,以及它是如何精确控制每一个数字的。


这段代码的核心任务是打印杨辉三角。为了让你理解得更透彻,我将整个程序拆解为四个核心阶段:“画布准备”、“边界构建”、“核心计算”和“格式化输出”。

🛠️ 第一阶段:画布准备与内存布局

  • 动态画布
    • int a[n][n]:这里定义了一个二维数组。你可以把它想象成一个正方形的棋盘。
    • 关键点:这里的 n 是由用户输入的。在 C99 标准及以后,C 语言允许使用变量来定义数组长度(这叫变长数组)。这意味着如果你输入 5,内存里就开辟 5x5 的空间;输入 10,就开辟 10x10。
  • 清零操作
    • = {0}:这步非常关键!它把整个棋盘的所有格子都初始化为 0
    • 为什么要清零? 杨辉三角是一个“直角三角形”形状的数据,但在二维数组(正方形)中,右上角其实是空的。如果不初始化为 0,那些没被计算到的角落可能会残留内存里的随机垃圾值,导致打印出错。

🏗️ 第二阶段:构建骨架(边界赋值)

这一层循环负责给杨辉三角“立规矩”。杨辉三角有一个铁律:每一行的开头和结尾都是 1

  • a[i][0] = 1(左墙)
    • i 代表行号。0 代表列号。
    • 这行代码强制规定:不管哪一行,第 1 个数字永远是 1。
  • a[i][i] = 1(斜墙)
    • 注意这里列号也是 i。这意味着第 0 行的第 0 个,第 1 行的第 1 个……
    • 这在数组中形成了一条对角线。它强制规定:每一行的最后一个有效数字也是 1。

通俗理解这就像盖房子先打地基和立柱子,先把三角形的两条边定死,中间的数才好算。

⚙️ 第三阶段:核心计算(递推逻辑)

这是代码的灵魂部分,也就是杨辉三角的数学规律:中间的数 = 它左肩上的数 + 它正上方的数

让我们通过一个具体的例子(假设 i=2,即第 3 行)来拆解这个公式:

  • 循环范围 j = 1; j < i

    • 为什么要从 j=1 开始?因为 j=0(第一个数)已经在上面被赋值为 1 了,不需要计算。
    • 为什么要 j < i?因为 j=i(最后一个数)也被赋值为 1 了。
    • 结论:这个循环只负责计算中间的那些数
  • 公式 a[i][j] = a[i-1][j-1] + a[i-1][j]

    • a[i][j]:当前位置(我想求的数)。
    • a[i-1][j-1]上一行前一列(左肩)。
    • a[i-1][j]上一行当前列(正上方/右肩)。

图解逻辑
如果你想求第 4 行第 2 个数,程序会伸手去上一行(第 3 行),把第 1 个数和第 2 个数抓过来相加。

🖨️ 第四阶段:格式化输出(修剪形状)

虽然我们在内存里定义的是 n x n 的正方形数组,但杨辉三角是三角形的。所以打印时必须“修剪”掉多余的部分。

  1. j <= i 的妙用

    • 第 0 行 (i=0):循环 j 从 0 到 0(打印 1 个数)。
    • 第 1 行 (i=1):循环 j 从 0 到 1(打印 2 个数)。
    • 第 2 行 (i=2):循环 j 从 0 到 2(打印 3 个数)。
    • 作用这确保了每一行只打印有效数据,不会把数组里后面那些初始化为 0 的垃圾数据打印出来。
  2. printf("\n")在外层循环中!!!

    • 每打印完一行数据,必须换行,否则所有数字会挤在一行里。

📌 深度总结:数据流向演示

假设输入 n=3,内存里的数组 a 是这样变化的:

1.初始状态(全0):

2.边界赋值后(立骨架)

  • a[0][0]=1a[0][0]=1
  • a[1][0]=1a[1][1]=1
  • a[2][0]=1a[2][2]=1

3.核心计算后(填肉)

  • 计算 a[2][1]:等于 a[1][0] + a[1][1] = 1 + 1 = 2

4.最终输出:

        程序只打印 j <= i 的部分,于是你看到了完美的三角形:

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐