21天C語言代碼訓(xùn)練營(yíng)(第三天)

上一篇最后留了一個(gè)打印楊輝三角的問題掂榔。這是C語言程序設(shè)計(jì)練習(xí)題中比較常見的一道題,今天我們將通過多種解法幫助大家熟悉C語言程序設(shè)計(jì)的基本思想酥泛。請(qǐng)大家跟隨我的思路一步步練習(xí)月趟,程序設(shè)計(jì)中解決問題的思路才是最珍貴的。

楊輝三角

1. 題目分析

上面這張圖就是楊輝三角撇簿,相信大家在中學(xué)數(shù)學(xué)課中學(xué)習(xí)過聂渊。它實(shí)際上是二項(xiàng)式(a + b)的n次方展開后各項(xiàng)的系數(shù)排成的三角形,它有如下特點(diǎn):

  • 每行左右兩邊都是1
  • 從第二行起四瘫,中間的每一個(gè)數(shù)是上一行里相鄰兩個(gè)數(shù)之和
  • 第n行有n個(gè)數(shù)字

2. 解法一

看到這個(gè)問題汉嗽,最容易想到的是創(chuàng)建一個(gè)二維數(shù)組。之后像填表一樣把每一行的數(shù)據(jù)依次填進(jìn)二維數(shù)組中找蜜。如圖所示:

楊輝三角二維數(shù)組

2.1 二維數(shù)組初始化

首先饼暑,我們需要?jiǎng)?chuàng)建一個(gè)二維數(shù)組(我們以10 * 10的二維數(shù)組為例),全部元素初始化為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;
    }

    // 打印二維數(shù)組中的三角形
    for (i = 0; i < n; i++)
    {
        for (j = 0; j <= i; j++)
            printf("%5d", array[i][j]);

        printf("\n");
    }
}

執(zhí)行結(jié)果:

執(zhí)行結(jié)果

這段代碼中需要注意:

  • 用宏MAX定義數(shù)組長(zhǎng)度,方便改寫
  • 數(shù)組初始化為0
  • 打印時(shí)使用“%5d”竭望,防止后面數(shù)字位數(shù)太多破壞打印格式

2.2 計(jì)算剩余單元格

代碼如下:

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

這段代碼中需要注意:

  • 從第三行開始計(jì)算(i = 2)
  • 每一個(gè)空格的內(nèi)容都是它左上方和上方兩個(gè)元素之和

2.3 最終結(jié)果

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

# 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];

    // 打印二維數(shù)組中的三角形
    for (i = 0; i < n; i++)
    {
        for (j = 0; j <= i; j++)
            printf("%5d", array[i][j]);

        printf("\n");
    }

    return 0;
}

執(zhí)行結(jié)果如下:

執(zhí)行結(jié)果

最終打印形式和楊輝三角還有距離邪码,請(qǐng)大家自己思考一下,如何把這些數(shù)字打印成標(biāo)準(zhǔn)的楊輝三角格式咬清。

這個(gè)解法是最樸素的方法闭专,一般大家都能想到。我們要做的只是把這個(gè)方法用代碼實(shí)現(xiàn)而已旧烧。在真正的程序設(shè)計(jì)工作中影钉,往往都是這樣先相處樸素解法,之后再分析哪些環(huán)節(jié)可以優(yōu)化掘剪。下面我們就看看這個(gè)方法能否優(yōu)化平委。

3. 解法二

解法一種兩組for循環(huán)看似比較冗余,我們希望能夠用一組循環(huán)完成所有工作夺谁。

# 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];
    }

    // 打印二維數(shù)組中的三角形
    for (i = 0; i < n; i++)
    {
        for (j = 0; j <= i; j++)
            printf("%5d", array[i][j]);

        printf("\n");
    }

    return 0;
}

執(zhí)行結(jié)果完全相同廉赔。此解法把填寫數(shù)字1的工作放入循環(huán)中肉微,減少了一個(gè)循環(huán)。

4. 解法三

解法二中的兩組循環(huán)其實(shí)都是對(duì)二維數(shù)組的遍歷蜡塌,第一遍填數(shù)字碉纳,第二遍打印。那我們能不能一次遍歷就完成既填空又打印的動(dòng)作呢馏艾。請(qǐng)看下面這段代碼:

# 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;
}

同樣的功能劳曹,這樣實(shí)現(xiàn)是否又簡(jiǎn)潔了一些呢?

5. 解法四

解法三還能優(yōu)化嗎琅摩?當(dāng)然可以铁孵,我們最終的目的是打印,并非保存房资,那么我們其實(shí)沒有必要用一個(gè)二維數(shù)組把所有的數(shù)字保存起來蜕劝。我們只需要在打印的時(shí)候讀取上一行的內(nèi)容,同時(shí)計(jì)算出當(dāng)前行內(nèi)容保存起來即可轰异。那么我們?cè)囍脙蓚€(gè)一維數(shù)組來完成熙宇。

# define MAX 10

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

// 兩個(gè)數(shù)組用來保存兩行數(shù)字
    int array1[MAX] = { 0 };
    int array2[MAX] = { 0 };

    int* pUp = array1; // 指向保存上一行數(shù)字的數(shù)組
    int* pDown = array2; // 指向保存當(dāng)前行數(shù)組的數(shù)組
    int* p = NULL; // 空指針用來進(jìn)行指針交換

    int index = 0; // 訪問下標(biāo)

    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;

    // 兩個(gè)指針指向內(nèi)容交換
        p = pUp;
        pUp = pDown;
        pDown = p;

        printf("\n");
    }

    return 0;
}

這段代碼的執(zhí)行效率很高,存儲(chǔ)空間使用的也比較少溉浙。但可讀性相對(duì)差一些。我們用了兩個(gè)數(shù)組array1和array2蒋荚,又用了兩個(gè)指針來管理這兩個(gè)數(shù)組戳稽。為什么不直接用數(shù)組名操作呢,因?yàn)閮蓚€(gè)數(shù)組的使用時(shí)交替進(jìn)行的期升,一個(gè)保存當(dāng)前行惊奇,一個(gè)保存上一行。

這個(gè)解法難度比較大播赁,初學(xué)者可以先不做了解颂郎。如果留言中需要具體講解的人數(shù)多,我會(huì)在下一篇中重點(diǎn)講解容为。

程序設(shè)計(jì)千變?nèi)f化乓序,這道題也遠(yuǎn)不止這四種解法。請(qǐng)大家在學(xué)習(xí)這四種的同時(shí)自己思考新的方法坎背。

6. 課后練習(xí)

今天的課后練習(xí)題出個(gè)簡(jiǎn)單的替劈,請(qǐng)編程打印出9*9乘法表。

最后得滤,我想說這個(gè)專題重在訓(xùn)練而不在講解陨献。如果只看講解不做練習(xí),那么提高的空間將會(huì)非常有限懂更。

我是天花板眨业,讓我們一起在軟件開發(fā)中自我迭代急膀。
如有任何問題,歡迎與我聯(lián)系龄捡。


上一篇:21天C語言代碼訓(xùn)練營(yíng)(第二天)
下一篇:21天C語言代碼訓(xùn)練營(yíng)(第四天)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末卓嫂,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子墅茉,更是在濱河造成了極大的恐慌命黔,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件就斤,死亡現(xiàn)場(chǎng)離奇詭異悍募,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)洋机,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門坠宴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人绷旗,你說我怎么就攤上這事喜鼓。” “怎么了衔肢?”我有些...
    開封第一講書人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵庄岖,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我角骤,道長(zhǎng)隅忿,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任邦尊,我火速辦了婚禮背桐,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蝉揍。我一直安慰自己链峭,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開白布又沾。 她就那樣靜靜地躺著弊仪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪杖刷。 梳的紋絲不亂的頭發(fā)上撼短,一...
    開封第一講書人閱讀 51,301評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音挺勿,去河邊找鬼曲横。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的禾嫉。 我是一名探鬼主播灾杰,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼熙参!你這毒婦竟也來了艳吠?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤孽椰,失蹤者是張志新(化名)和其女友劉穎昭娩,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體黍匾,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡栏渺,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了锐涯。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片磕诊。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖纹腌,靈堂內(nèi)的尸體忽然破棺而出霎终,到底是詐尸還是另有隱情,我是刑警寧澤升薯,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布莱褒,位于F島的核電站,受9級(jí)特大地震影響涎劈,放射性物質(zhì)發(fā)生泄漏保礼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一责语、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧目派,春花似錦坤候、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至谅摄,卻和暖如春徒河,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背送漠。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工顽照, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓代兵,卻偏偏與公主長(zhǎng)得像尼酿,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子植影,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容