美文网首页计算机技术宅计算机
21天C语言代码训练营(第三天)

21天C语言代码训练营(第三天)

作者: 天花板 | 来源:发表于2015-11-22 18:02 被阅读5982次

上一篇最后留了一个打印杨辉三角的问题。这是C语言程序设计练习题中比较常见的一道题,今天我们将通过多种解法帮助大家熟悉C语言程序设计的基本思想。请大家跟随我的思路一步步练习,程序设计中解决问题的思路才是最珍贵的。

杨辉三角

1. 题目分析

上面这张图就是杨辉三角,相信大家在中学数学课中学习过。它实际上是二项式(a + b)的n次方展开后各项的系数排成的三角形,它有如下特点:

  • 每行左右两边都是1
  • 从第二行起,中间的每一个数是上一行里相邻两个数之和
  • 第n行有n个数字

2. 解法一

看到这个问题,最容易想到的是创建一个二维数组。之后像填表一样把每一行的数据依次填进二维数组中。如图所示:

杨辉三角二维数组

2.1 二维数组初始化

首先,我们需要创建一个二维数组(我们以10 * 10的二维数组为例),全部元素初始化为0,之后把所有1的位置填上。代码如下:

# define MAX 10

int main()
{
    int i, j, n = MAX;
    int array[MAX][MAX] = { 0 };

    for (i = 0; i < n; i++)
    {
        array[i][0] = 1;
        array[i][i] = 1;
    }

    // 打印二维数组中的三角形
    for (i = 0; i < n; i++)
    {
        for (j = 0; j <= i; j++)
            printf("%5d", array[i][j]);

        printf("\n");
    }
}

执行结果:

执行结果

这段代码中需要注意:

  • 用宏MAX定义数组长度,方便改写
  • 数组初始化为0
  • 打印时使用“%5d”,防止后面数字位数太多破坏打印格式

2.2 计算剩余单元格

代码如下:

for (i = 2; i < n; i++)
    for (j = 1; j < i; j++)
        array[i][j] = array[i - 1][j - 1] + array[i - 1][j];

这段代码中需要注意:

  • 从第三行开始计算(i = 2)
  • 每一个空格的内容都是它左上方和上方两个元素之和

2.3 最终结果

于是我们得到了完整的程序:

# define MAX 10

int main()
{
    int i, j, n = MAX;
    int array[MAX][MAX] = { 0 };

    for (i = 0; i < n; i++)
    {
        array[i][0] = 1;
        array[i][i] = 1;
    }

    for (i = 2; i < n; i++)
        for (j = 1; j < i; j++)
            array[i][j] = array[i - 1][j - 1] + array[i - 1][j];

    // 打印二维数组中的三角形
    for (i = 0; i < n; i++)
    {
        for (j = 0; j <= i; j++)
            printf("%5d", array[i][j]);

        printf("\n");
    }

    return 0;
}

执行结果如下:

执行结果

最终打印形式和杨辉三角还有距离,请大家自己思考一下,如何把这些数字打印成标准的杨辉三角格式。

这个解法是最朴素的方法,一般大家都能想到。我们要做的只是把这个方法用代码实现而已。在真正的程序设计工作中,往往都是这样先相处朴素解法,之后再分析哪些环节可以优化。下面我们就看看这个方法能否优化。

3. 解法二

解法一种两组for循环看似比较冗余,我们希望能够用一组循环完成所有工作。

# define MAX 10

int main()
{
    int i, j, n = MAX;
    int array[MAX][MAX] = { 0 };

    for (i = 0; i < n; i++)
    {
        array[i][0] = 1;
        for (j = 1; j <= i; j++)
            array[i][j] = array[i - 1][j - 1] + array[i - 1][j];
    }

    // 打印二维数组中的三角形
    for (i = 0; i < n; i++)
    {
        for (j = 0; j <= i; j++)
            printf("%5d", array[i][j]);

        printf("\n");
    }

    return 0;
}

执行结果完全相同。此解法把填写数字1的工作放入循环中,减少了一个循环。

4. 解法三

解法二中的两组循环其实都是对二维数组的遍历,第一遍填数字,第二遍打印。那我们能不能一次遍历就完成既填空又打印的动作呢。请看下面这段代码:

# define MAX 10

int main()
{
    int i, j, n = MAX;
    int array[MAX][MAX] = { 0 };

    for (i = 0; i < n; i++)
    {
        array[i][0] = 1;
        printf("%5d", 1);

        for (j = 1; j <= i; j++)
        {
            array[i][j] = array[i - 1][j - 1] + array[i - 1][j];
            printf("%5d", array[i][j]);
        }

        printf("\n");
    }

    return 0;
}

同样的功能,这样实现是否又简洁了一些呢?

5. 解法四

解法三还能优化吗?当然可以,我们最终的目的是打印,并非保存,那么我们其实没有必要用一个二维数组把所有的数字保存起来。我们只需要在打印的时候读取上一行的内容,同时计算出当前行内容保存起来即可。那么我们试着用两个一维数组来完成。

# define MAX 10

int main()
{
    int i, j, n = MAX;

// 两个数组用来保存两行数字
    int array1[MAX] = { 0 };
    int array2[MAX] = { 0 };

    int* pUp = array1; // 指向保存上一行数字的数组
    int* pDown = array2; // 指向保存当前行数组的数组
    int* p = NULL; // 空指针用来进行指针交换

    int index = 0; // 访问下标

    for (i = 0; i < n; i++)
    {
        printf("%5d", 1);
        *(pDown + index++) = 1;

        for (j = 1; j <= i; j++)
        {
            *(pDown + index) = *(pUp + index - 1) + *(pUp + index);
            printf("%5d", *(pDown + index));
             index++;
        }

        index = 0;

    // 两个指针指向内容交换
        p = pUp;
        pUp = pDown;
        pDown = p;

        printf("\n");
    }

    return 0;
}

这段代码的执行效率很高,存储空间使用的也比较少。但可读性相对差一些。我们用了两个数组array1和array2,又用了两个指针来管理这两个数组。为什么不直接用数组名操作呢,因为两个数组的使用时交替进行的,一个保存当前行,一个保存上一行。

这个解法难度比较大,初学者可以先不做了解。如果留言中需要具体讲解的人数多,我会在下一篇中重点讲解。

程序设计千变万化,这道题也远不止这四种解法。请大家在学习这四种的同时自己思考新的方法。

6. 课后练习

今天的课后练习题出个简单的,请编程打印出9*9乘法表。

最后,我想说这个专题重在训练而不在讲解。如果只看讲解不做练习,那么提高的空间将会非常有限。

我是天花板,让我们一起在软件开发中自我迭代。
如有任何问题,欢迎与我联系。


上一篇:21天C语言代码训练营(第二天)
下一篇:21天C语言代码训练营(第四天)

相关文章

网友评论

  • 8adafd09129a:#include <stdio.h>
    #include <stdlib.h>

    int main()
    {
    int i,j;
    for(i=1;i<=9;i++)
    {
    for(j=1;j<=i;j++)
    {
    if(i==j)
    {
    printf("%d*%d=%d\n",i,j,i*j);
    }
    else
    {
    printf("%d*%d=%d ",i,j,i*j);
    }

    }
    }
    return 0;
    }
  • 寒山半秋:#include <stdio.h>

    int main(int argc, const char * argv[]) {
    int a, b, c;
    for (a = 1; a < 10; a++) {
    for (b = 1; b <= a; b++) {
    c = a * b;
    printf("%d * %d = %2d ", b, a, c);
    if (b == a) {
    printf("\n");
    }
    }
    }
    return 0;
    }
  • xyy的简书:pdown为什么要等于p呢
    天花板:@叩_97ca 因为要交换呀
  • 59d3e1a116cd:从哪里下载编程工具,能告诉我吗?
  • ID一龍族丨:#include <stdio.h>
    #define n 10
    int main()
    {
    int i, j;
    int a[n][n];



    for (i = 0; i < n; i++)
    {
    for (j = n - i ; j > 0 ; j --)
    {
    printf(" ");
    }
    for (j = 0; j <= i; j++)
    {
    if (i == j || j == 0)
    {
    a[i][j] = 1;
    }
    else
    {
    a[i][j] = a[i - 1][j - 1] + a[i-1][j];
    }
    printf("%4d", a[i][j]);

    }
    printf("\n");
    }





    system("pause");
    return 0;
    }
  • 流影之愁:第四种解法终于明白了,自己也编译出来了,谢谢天花板的讲解 ,对我很有用😊😊
  • NiceBlueChai:打印这个不难啊关键是打印出来的排版怎么搞,自己搞不出第一张图片那样(金字塔形状),复制楼主的代码结果也是没排好的杨辉三角
  • cd002734b69a:有一点不懂,方法二中出现了array[-1]为什么不会报错?
    cd002734b69a:嗯嗯,明白了,谢谢
    天花板:@当凹遇上凸 你说的是array[i - 1]这句吗,当 i = 0 时这句话根本执行不到。所以array[-1]根本没有出现。不信你运行一下这段代码试试。
  • ee3a0b4d6d51:厉害了
  • f8f0408f304f:程序的图片怎么显示不全啊?
  • bdb27209c62e:打卡喽
  • 清风景行:够专业
  • b00a68d5e092:看起来好高大上的样纸
  • a01ab4ecf567:有没有vb的呀
  • 79521e6b52e8:21天。。。。也太短了。。。
  • c9ab8809f4cf:就喜欢你的文章
  • 0af3bcf3ab0a:感兴趣,不知道怎么入门,求教!
    天花板:@社会你威哥 请看我的另一个博文系列 http://www.jianshu.com/p/24e4b70c4bbd
  • 082af968c374:解法四不能实现,求详解。。
  • ab841cabb2de:我现在刚学习c语言,希望你能多讲些哦,最好是能多介绍能让初学者提升的书籍或者资料。你写的这些我每天都看,很好的。感谢有你这样的大神
  • 9cd83ad216e3:#include<stdio.h>
    int main()
    {
    int i,j;
    int a[9][9];
    for(i=0;i<9;i++)
    {
    for(j=0;j<9;j++)
    a[i][j]=(i+1)*(j+1);
    }
    for(i=0;i<9;i++)
    {
    for(j=0;j<=i;j++)
    {
    printf("%3d*%d=",i+1,j+1);
    printf("%d",a[i][j]);
    }
    printf("\n");
    }
    }
  • 4ed6afef78f9:打卡,难的做不出来,简单的还行。
    int main()
    {
    int a,b,c;
    for (a =1; a<10; a++) {
    for (b = 1; b<=a; b++) {
    printf("%d*%d=%d ",b,a,a*b);
    }
    printf("\n");
    }
    }
  • 浅念boy:大一新生,表示上一篇的菱形也没有看懂,C语言上课基本没有学,怎么破?
    浅念boy:@d4b1f32041af 谢谢
    天花板:@浅念boy 从头开始学吧,慢慢来~
    3011f7aab80f:@浅念boy 只能先背下来了,以后慢慢理解了

本文标题:21天C语言代码训练营(第三天)

本文链接:https://www.haomeiwen.com/subject/upcrhttx.html