接着昨天的倒計時,今天寫了一個菱形的算法。題目:輸入一個菱形的高n(必須爲奇數),即行數,也是正中間行的星號個數,打印用星號組成的菱形。如下圖,高爲9的菱形:
看到此題,想到的第一個方法就是先打印上半部分,再打印下半部分。這個仔細觀察,就能找到規律,寫出來不難。後來想能否不分上下部分,直接for循環,從1到n,一次性全部打印出來。主要是想把上下部分的打印程序整合在一起,相當於都調用同一個帶參數的函數即可。最後也沒想到什麼好方法,就從每行的前半部分空格和後半部分星號開始思路。
前半部的空格都好應付。空格個數在上半部分從n/2減到0,再從下半部分的0增加到n/2。空格個數與行數i的關係分別是:(n+1)/2-i和i-(n+1)/2。
後半部的星號個數都是上半部分每行加2,加到n;然後下半部分逐行再減2,減到1。經過分析,星號個數與行數i的關係分別是:2*i-1和n-2*(i-(n+1)/2)。主要是下半部分的公式看上去比較複雜,其實可以從兩個角度來理解(設m=(n+1)/2,即正中間的行數。)。
一、垂直對稱法。這裏每行都可以理解爲打印n個字符,中間是星號,兩邊是同等個數的空格,即對稱於豎直的對角線,也就是垂直對稱。上面已分析出空格數與行數的關係是i-m,所以中間的星號是總的字符數n,再減去兩邊的空格數2*(i-m),即n-2*(i-m)。
二、疊加相減法。每行中,前面空格數加上後面星號數的打印總數s,是不是從n開始在逐行遞減(以-1爲增量)?每行打印總數s與n,是不是存在一個這麼的關係:s=n-(i-m),即n減去每行的空格數?星號總數,也就是打印總數s減去每行的空格數了,即s-(i-m)=n-2*(i-m)。
代碼如下:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <windows.h>
int main(int argc, char **argv)
{
UCHAR n=9;
UCHAR m,a,b,i,j;
if(n%2 == 0)
return -1;
m=(n+1)/2;
for(i=1; i<=n; i++){
if(i < m){
a = m-i;
b = 2*i -1; //a+b = m+i-1
}else{
a = i-m;
b = n-2*(i-m); //a+b = n-(i-m)
}
for(j=1; j<=a; j++)
printf(" ");
for(j=1; j<=b; j++)
printf("*");
printf("\n");
}
system("pause");
}