





摘要:文章首先介紹了楊輝三角和二項(xiàng)式的基本原理,提出了三種求楊輝三角的程序算法,這三種算法分別是:組合數(shù)法、遞歸法和隊(duì)列法,使用Java語言在Eclipse平臺上實(shí)現(xiàn)了這三種算法,并對這三種算法的運(yùn)行效率和時間復(fù)雜度進(jìn)行了測試分析,得出了隊(duì)列法最優(yōu)的結(jié)論。
關(guān)鍵詞:楊輝三角;二項(xiàng)式;遞歸;隊(duì)列
中圖分類號:TP391" " " 文獻(xiàn)標(biāo)識碼:A
文章編號:1009-3044(2022)33-0034-04
1 引言
楊輝三角本質(zhì)上是一組數(shù)的集合,是二項(xiàng)式系數(shù)呈三角形一種幾何排列,其通過圖形直觀地顯示了二項(xiàng)式系數(shù),把組合數(shù)內(nèi)在的一些代數(shù)性質(zhì)直觀地從圖形中體現(xiàn)出來,是把一系列離散型的正整數(shù)與圖形相結(jié)合后所形成的一個特殊的三角形。楊輝三角是由我國南宋數(shù)學(xué)家楊輝發(fā)現(xiàn)的,是中國古代數(shù)學(xué)一項(xiàng)優(yōu)秀的研究成果,法國科學(xué)家帕斯卡在390多年后也發(fā)現(xiàn)了此成果,所以楊輝三角有時候也稱為帕斯卡三角。
Java是一種面向?qū)ο蟾呒壘幊陶Z言,不僅具有面向?qū)ο笳Z言的繼承、封裝和多態(tài)優(yōu)點(diǎn),還揚(yáng)棄了難以理解的一些理論,比如多繼承,所以Java語言具有功能強(qiáng)勁和簡單實(shí)用兩個特點(diǎn),允許程序員快速高效地進(jìn)行復(fù)雜編程。Java語言還具有分布式、平臺獨(dú)立與可移植性、多線程和動態(tài)性等特點(diǎn)。Java語言可以實(shí)現(xiàn)桌面應(yīng)用程序、Web應(yīng)用程序、分布式系統(tǒng)和嵌入式系統(tǒng)應(yīng)用程序等[1]。
本文運(yùn)用Java語言中的桌面應(yīng)用程序?qū)崿F(xiàn)了楊輝三角的形成和顯示,而且使用組合數(shù)、遞歸和隊(duì)列三種不同的方法進(jìn)行了實(shí)現(xiàn),并對這三種方法的優(yōu)劣進(jìn)行了對比和分析。
2 楊輝三角
一個二項(xiàng)式如下表示:
[(x+y)n=C0n*xn+C1n*xn-1*y+C2n*xn-2*y2]+...+[Cnn*yn]" " "(1)
楊輝三角是由一系列二項(xiàng)式中的系數(shù)(組合數(shù))構(gòu)成的,一個楊輝三角的顯示圖如圖1所示。
lt;E:\2022知網(wǎng)文件\33\2xs202233\Image\image2.pnggt;
圖1" "楊輝三角
第一行為k=0的二項(xiàng)式的系數(shù),第二行是k=1的二項(xiàng)式的系數(shù),以此類推,第n+1行是k=n的二項(xiàng)式的系數(shù),楊輝三角所對應(yīng)的圖形是一個等腰三角形,兩條腰上的數(shù)值都是1,其余的一般項(xiàng)的數(shù)值滿足:
[Crk=Crk-1]+[Cr-1k-1]nbsp; " " " " " " " " " " " " "(2)
一般項(xiàng)的數(shù)值等于上一行相鄰的兩個項(xiàng)的數(shù)值之和[2]。
3 程序設(shè)計
由于楊輝三角中數(shù)值具有規(guī)律性,所以可以通過計算機(jī)編程實(shí)現(xiàn),本研究采用了三種不同的方法實(shí)現(xiàn)了楊輝三角,所采用的編程語言是Java語言,具體Java版本號為JDK1.9,開發(fā)平臺使用是Eclipse 4.11,項(xiàng)目結(jié)構(gòu)如圖2所示。
lt;E:\2022知網(wǎng)文件\33\2xs202233\Image\image3_1.pnggt;
圖2" "項(xiàng)目結(jié)構(gòu)圖
項(xiàng)目名稱為Pyanghui,然后在此項(xiàng)目中建立了5個類,Cmain是主函數(shù)入口類,Cyang1是通過求組合數(shù)實(shí)現(xiàn)楊輝三角的類,Cyang2是通過遞歸實(shí)現(xiàn)楊輝三角的類,Cyanghui是通過隊(duì)列實(shí)現(xiàn)楊輝三角的類,queue為隊(duì)列類[3]。
3.1 組合數(shù)法
組合數(shù)法的思想是:先求排列值[Pnn]=n!,再求組合值[Cmn]=n!/(m!*(n-m)!),然后再分行顯示,每行先打印相應(yīng)的空格數(shù),再顯示一系列組合的值,其對應(yīng)的流程圖如圖3所示。
lt;E:\2022知網(wǎng)文件\33\2xs202233\Image\image4_1.pnggt;
圖3" "方法1流程圖
具體的java程序代碼如下:
publicclass Cyang1 {
//求階乘n!函數(shù)
publicint mul(int n)
{
int m;
if(n==0)
m=1;
else
{m=1;
for(int i=1;ilt;=n;i++)
m=m*i; }
return(m);}
//求組合數(shù)[Cmn]函數(shù)
publicint zuhe(int n,int m)
{if(nlt;m) //不合法情況
{System.out.println(\"不合法!??!\");
System.exit(0);
return(0);}
else
{return(mul(n)/(mul(m)*mul(n-m))) ;}
}
//打印組合數(shù)[Cmn]函數(shù)
publicvoid ydisplay(int n,int m)
{System.out.println(zuhe(n,m));}
//求n行楊輝三角函數(shù)
publicvoid calyang(int n)
{//j控制行數(shù)
for(int j=0;jlt;=n;j++)
{//打印相關(guān)空格
for(int m=0;mlt;=n-j;m++)
System.out.print(\"\");
//顯示一行中的所有組合數(shù)
for(int k=0;klt;=j;k++)
{
System.out.print(zuhe(j,k));//換行
System.out.print(\"\");//兩個數(shù)之間打印空格
}
System.out.println();//換行
}}
}
顯然ydisplay函數(shù)是通過二重循環(huán)實(shí)現(xiàn),而且最里層循環(huán)調(diào)用了zuhe函數(shù),zuhe函數(shù)又調(diào)用了mul函數(shù),mul函數(shù)使用一重循環(huán)實(shí)現(xiàn),其問題規(guī)模為n,所以mul函數(shù)和zuhe函數(shù)的算法時間復(fù)雜度為O(n),ydisplay函數(shù)的時間復(fù)雜度為O([n3])。
Java語言里int值占用4個字節(jié),其取值范圍為(-2147483648到2147483647),13!gt;2147483647,所以當(dāng)用mul函數(shù)求13的階乘時會溢出,calyang函數(shù)只能求0到12的楊輝三角[4]。
lt;E:\2022知網(wǎng)文件\33\2xs202233\Image\image5.pnggt;
圖4" "求組合數(shù)遞歸過程圖
3.2 遞歸法
楊輝三角中的組合數(shù)[Cmn]有一定規(guī)律,其規(guī)律為:如果m=0或者m等于n,則此組合數(shù)為1,否則[Cmn]=[Cmn-1]+[Cm-1n-1],例如求[C35]的過程如圖4所示。
此方法對應(yīng)算法思想和流程圖除了求組合數(shù)有差異外,其余的均類似,具體的Java代碼為:
public class Cyang2 {
//求組合數(shù)函數(shù),n為上標(biāo),m為下標(biāo)
public int caly(int n,int m)
{
//判斷合法情況,上下標(biāo)都是非零整數(shù),上標(biāo)大于等于下標(biāo)
if(ngt;=0amp;amp;mgt;=0amp;amp;ngt;=m)
{ if(m==0)
//遞歸基1:第一列為1
return(1);
else
if(n==m)
//遞歸基2:行等于列時返回1
return(1);
Else
//遞歸調(diào)用
return(caly(n-1,m)+caly(n-1,m-1));}
Else
//不合法時返回-1
return(-1);}
//顯示楊輝三角函數(shù),n為楊輝三角行數(shù)
public void ydisplay2(int n)
{//i控制楊輝三角行數(shù)
for(int i=0;ilt;=n;i++)
{//顯示每行的空格
for(int m=0;mlt;=n-i;m++)
System.out.print(\"\");
//打印每行的組合數(shù),j控制每行的具體數(shù)目
for(int j=0;jlt;=i;j++)
System.out.print(caly(i,j)+\"\");
//換行
System.out.println();
}}}
此方法也是通過二重循環(huán)實(shí)現(xiàn),其中內(nèi)層循環(huán)調(diào)用遞歸函數(shù)caly,遞歸函數(shù)的時間復(fù)雜度為O(n),所以此方法的時間復(fù)雜度也為O([n3])。通過此方法求組合數(shù)不涉及乘法,只使用了加法,當(dāng)n=30時才會發(fā)生溢出,所以此方法能求從n=0到n=29的楊輝三角。遞歸法也有其相應(yīng)的缺陷,很多組合數(shù)被重復(fù)運(yùn)算多次,降低了算法的效率,例如在圖4中,[C12]被計算了3次[5]。
3.3 隊(duì)列法
隊(duì)列法的基本思想為:(1)當(dāng)楊輝三角只有一行時,打印相應(yīng)空格和1;(2)當(dāng)楊輝三角有n行時,先執(zhí)行(1),然后0進(jìn)隊(duì)列,0是第一行和第兩行楊輝三角組合數(shù)的分隔值,然后連續(xù)兩個1進(jìn)隊(duì)列,此時隊(duì)列有隊(duì)尾到隊(duì)首的元素,分別為1、1、0,一個0再進(jìn)隊(duì)列,這個0是第二行和第三行楊輝三角組合數(shù)的分隔值,此時隊(duì)首值poll值出,因?yàn)槿绻?dāng)前楊輝三角組合值不在邊界,其等于上一行相鄰元素之和,要顯示的值evs等于出隊(duì)值poll加當(dāng)前隊(duì)首值first,如果evs>0,則顯示相關(guān)空格和evs,如果firstl等于0,不再對隊(duì)列進(jìn)行操作,換行顯示下一行的楊輝三角值;(3)反復(fù)進(jìn)行第二步,直到第n行的楊輝三角值顯示完畢。具體的求三行楊輝三角的例子如圖5所示。
lt;E:\2022知網(wǎng)文件\33\2xs202233\Image\image6.pnggt;
圖5" " 求組合數(shù)遞歸過程圖
左邊三個虛線方框代表求三行楊輝三角組合值的過程,右部三個三角形圖形表示顯示楊輝三角組合值的過程。初始隊(duì)列為空,顯示1,對應(yīng)第一行的楊輝三角值;0、1、1、0按順序進(jìn)隊(duì)列,0出隊(duì)列,0不顯示,0加1等于1進(jìn)隊(duì)列,1出隊(duì)列,顯示空格和1,1加1等于2進(jìn)隊(duì)列,1出隊(duì)列,1加0等于1進(jìn)隊(duì)列,0不再出隊(duì)列,此時第二行顯示完畢,進(jìn)行換行;0進(jìn)隊(duì)列,此時隊(duì)列為0、1、2、1、0,0出隊(duì)列不顯示,0加1等于1進(jìn)隊(duì)列,然后1出隊(duì)列,顯示空格和1,1加2等于3進(jìn)隊(duì)列,2出隊(duì)列,2加1等于3進(jìn)隊(duì)列,1出隊(duì)列,0加1等于1進(jìn)隊(duì)列,顯示1和空格,0不再出隊(duì)列,此時第三行顯示完畢,進(jìn)行換行,隊(duì)列中的值為1,3,3,1,0,這是為第四行顯示做準(zhǔn)備的,顯然在顯示第n行楊輝三角值的過程中,第n+1行的楊輝三角值已經(jīng)求好存儲在隊(duì)列中[6]。
具體的Java代碼為:
public class Cyanghui {
//楊輝三角從0到n總共n+1行
public void fyang(int n)
//處理第一行情況
{if (n==0)
{for(int i=1;ilt;=n;i++)
System.out.print(\"\");
System.out.println('1');}
else
//其余情況
{for(int i=1;ilt;=n;i++)
System.out.print(\"\");
System.out.println('1');
//創(chuàng)建隊(duì)列
queue Q=new queue();
Q.offer(0);
Q.offer(1);
Q.offer(1);
int xfir=0;
int evs=0;
for(int k=1;klt;n;k++)
//處理空格
{for(int i=1;ilt;=n-k;i++)
System.out.print(\"\");
//換行標(biāo)志0進(jìn)隊(duì)列
Q.offer(0);
do
{
xfir=Q.poll();
//大于0才顯示
if(xfirgt;0)
System.out.print(xfir+\"\");
evs=xfir+Q.first();
Q.offer(evs);
xfir=Q.first();
} while(xfirgt;0);//只有隊(duì)首值大于0才繼續(xù)執(zhí)行
System.out.println();
}}}}
隊(duì)列類 queue可以通過自己編寫實(shí)現(xiàn),也可以使用Java語言中隊(duì)列類進(jìn)行實(shí)現(xiàn)。
此方法是通過三重循環(huán)實(shí)現(xiàn),所以此方法的時間復(fù)雜度也為O([n3])。通過此方法求組合數(shù)不涉及乘法,同樣只使用了加法,當(dāng)n=30時才會發(fā)生溢出,所以此方法能求從n=0到n=29的楊輝三角。此方法沒有重復(fù)計算組合數(shù),所以算法的效率高于方法二。
3.4 算法實(shí)驗(yàn)分析
在Cmain類中使用如下代碼對這三種算法進(jìn)行運(yùn)行時間計算:
long Tbegin=System.nanoTime();" "http://獲取算法開始時間,單位為納秒
分別運(yùn)行三種方法;
long Tend=System.nanoTime(); //獲取算法結(jié)束時間
System.out.println(\"算法運(yùn)行時間: \"+(endTime-startTime)+\"ns\");
在CPU為酷睿5(CORE5)和操作系統(tǒng)為Win10的工作站上分別運(yùn)行三種算法,三種算法的運(yùn)行時間和對應(yīng)行數(shù)的關(guān)系如表1所示。
表1" "算法運(yùn)行時間和行數(shù)對照圖
[算法
時間(納秒)
行數(shù) 5行 10行 15行 20行 25行 組合數(shù) 2465400 3962150 不支持 不支持 不支持 遞歸 2520000 3989950 8245200 12647200 17567900 隊(duì)列 2149900 3679900 7388300 10290100 14602600 ]
通過表1可以得出隊(duì)列法最優(yōu),遞歸法的算法效率次之,而組合數(shù)法因?yàn)橐绯龅木壒剩渲荒苤С?到12行的楊輝三角的計算[7]。
4 結(jié)論
本研究闡述了二項(xiàng)式的基本原理,二項(xiàng)式的值是楊輝三角的基本組成元素,使用Java語言和Eclipse平臺通過組合數(shù)、遞歸和隊(duì)列三種算法實(shí)現(xiàn)了楊輝三角的運(yùn)算和顯示,并對這三種算法的時間復(fù)雜度和效率進(jìn)行了分析,得出了遞歸算法最優(yōu),其運(yùn)行時間和算法效率都高于其余兩種算法。
本文所介紹的三種算法的運(yùn)行范圍因?yàn)檎麛?shù)溢出的緣故有限,組合數(shù)算法只能求行數(shù)從0到12的楊輝三角,遞歸法和隊(duì)列法只能求行數(shù)從0到29的楊輝三角,運(yùn)行范圍可以考慮通過字符隊(duì)列和大數(shù)加法進(jìn)行擴(kuò)大,這也是下一步的研究方向[8]。
參考文獻(xiàn):
[1] 王先東.楊輝三角中的奇數(shù)與偶數(shù)[J].數(shù)學(xué)通報,2009,48(5):62-63,66.
[2] 楊明順.楊輝三角的若干性質(zhì)研究[J].渭南師范學(xué)院學(xué)報,2016,31(4):9-12.
[3] 李旭東.再探“楊輝三角”中的行列式[J].數(shù)學(xué)學(xué)習(xí)與研究,2013(23):111.
[4] 馮潔,吳芳.探討C語言中輸出楊輝三角的教學(xué)方法[J].電腦知識與技術(shù)(學(xué)術(shù)交流),2007,3(13):113-113,115.
[5] 宋鈺.經(jīng)典數(shù)據(jù)結(jié)構(gòu)隊(duì)列的研究和實(shí)現(xiàn)[J].電腦編程技巧與維護(hù),2019(12):14-15.
[6] 陳竹云,葉雯.數(shù)據(jù)結(jié)構(gòu)中隊(duì)列的應(yīng)用研究[J].電腦知識與技術(shù),2017,13(3):5-7.
[7] 沈華.數(shù)據(jù)結(jié)構(gòu)課程中棧和隊(duì)列實(shí)驗(yàn)教學(xué)方案設(shè)計[J].教育教學(xué)論壇,2016(24):274-276.
[8] 耿國華.數(shù)據(jù)結(jié)構(gòu)[M].北京:高等教育出版社,2005.
【通聯(lián)編輯:代影】