杨辉三角-附C语言实现方法
杨辉三角
杨辉三角是一种由数字排列成的三角形数表,其核心规律为:每一行两端的数字为 1,中间的每个数字等于其上方两数之和。例如,前 5 行如下:
11 11 2 11 3 3 11 4 6 4 1
一、历史与数学意义
- 起源:杨辉三角最早由北宋数学家贾宪(约 1050 年)提出,后由南宋数学家杨辉在 1261 年的《详解九章算法》中记载并推广,比欧洲的 “帕斯卡三角” 早约 600 年。
- 数学本质:每一行的数字对应二项式展开式的系数。例如,((a+b)^n)的展开式系数恰好是杨辉三角的第(n+1)行。 例如: (a+b)3=a3+3a2b+3a**b2+b3 对应第4行:1 3 3 1
- 组合数关联:第n行第k个数(从 0 开始计数)等于组合数(C(n, k)),即从n个元素中选k个的方式数。
二、核心性质
- 对称性:每一行的数字左右对称,即(C(n, k) = C(n, n-k))。
- 行和规律:第n行所有数字之和为(2^n)。例如,第 3 行和为(1+2+1=4=2^2)。
- 质数特性:若某行(除两端的 1 外)所有数字都能被行数整除,则该行数必为质数。例如,第 5 行(1 4 6 4 1)的数字均能被 5 整除,而 5 是质数。
- 斐波那契数列:按特定斜线相加可得到斐波那契数列。例如,第 0 斜线(全 1)和为 1,第 1 斜线(1,1)和为 2,第 2 斜线(1,2)和为 3,依此类推。
三、C 语言实现方法
1. 二维数组法(基础实现)
#include <stdio.h>void printYangHui(int rows) {int arr[rows][rows];for (int i = 0; i < rows; i++) {for (int j = 0; j <= i; j++) {if (j == 0 || j == i)arr[i][j] = 1; // 两端为1elsearr[i][j] = arr[i-1][j-1] + arr[i-1][j]; // 中间数为上方两数之和}}// 打印时添加空格对齐for (int i = 0; i < rows; i++) {for (int k = 0; k < rows - i - 1; k++)printf(" "); // 控制缩进for (int j = 0; j <= i; j++)printf("%4d", arr[i][j]); // 每个数字占4个字符宽度printf("\n");}
}int main() {int rows;printf("输入行数:");scanf("%d", &rows);printYangHui(rows);return 0;
}
输出示例(输入 5):
11 11 2 11 3 3 11 4 6 4 1
2. 一维数组优化(节省内存)
#include <stdio.h>void printYangHui(int rows) {int prev[rows], curr[rows];for (int i = 0; i < rows; i++) {curr[0] = curr[i] = 1; // 每行两端为1// 计算中间数(仅需上一行的数据)for (int j = 1; j < i; j++)curr[j] = prev[j-1] + prev[j];// 打印当前行for (int k = 0; k < rows - i - 1; k++)printf(" ");for (int j = 0; j <= i; j++)printf("%4d", curr[j]);printf("\n");// 保存当前行供下一行使用for (int j = 0; j <= i; j++)prev[j] = curr[j];}
}int main() {int rows;printf("输入行数:");scanf("%d", &rows);printYangHui(rows);return 0;
}
优点:仅需两个一维数组,空间复杂度从(O(n^2))降为(O(n))。
3. 动态内存分配(支持大行数)
#include <stdio.h>
#include <stdlib.h>void printYangHui(int rows) {int **arr = (int **)malloc(rows * sizeof(int *));for (int i = 0; i < rows; i++) {arr[i] = (int *)malloc((i+1) * sizeof(int));arr[i][0] = arr[i][i] = 1;for (int j = 1; j < i; j++)arr[i][j] = arr[i-1][j-1] + arr[i-1][j];}// 打印for (int i = 0; i < rows; i++) {for (int k = 0; k < rows - i - 1; k++)printf(" ");for (int j = 0; j <= i; j++)printf("%4d", arr[i][j]);printf("\n");free(arr[i]); // 释放每行内存}free(arr); // 释放二维数组内存
}int main() {int rows;printf("输入行数:");scanf("%d", &rows);printYangHui(rows);return 0;
}
注意:需手动释放内存以避免内存泄漏。
四、常见问题与优化
- 整数溢出:当行数超过 20 时,组合数可能超过
int
范围。可改用long long
或动态计算组合数(避免阶乘直接计算)。 - 打印对齐:若数字位数不一致(如 1000),需动态计算最大数字的位数,调整空格数。
- 数组初始化:局部数组未初始化可能包含垃圾值,需显式初始化(如
int arr[N] = {1};
)。
五、扩展应用
- 组合数计算:直接通过杨辉三角获取(C(n, k))。
- 动态规划:如路径计数问题,可利用杨辉三角的递推思想。
- 数论研究:探索质数、斐波那契数列等隐藏规律。