MATLAB程序設計.doc_第1頁
MATLAB程序設計.doc_第2頁
MATLAB程序設計.doc_第3頁
MATLAB程序設計.doc_第4頁
MATLAB程序設計.doc_第5頁
已閱讀5頁,還剩48頁未讀 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

MATLAB程序設計方法及若干程序實例樊雙喜 (河南大學數(shù)學與信息科學學院 開封475004)摘 要 本文通過對MATLAB程序設計中的若干典型問題做簡要的分析和總結,并在此基礎上著重討論了有關算法設計、程序的調試與測試、算法與程序的優(yōu)化以及循環(huán)控制等方面的問題.還通過對一些程序實例做具體解析,來方便讀者進行編程訓練并掌握一些有關MATLAB程序設計方面的基本概念、基本方法以及某些問題的處理技巧等.此外,在文章的最后還給出了幾個常用數(shù)學方法的算法程序,供讀者參考使用.希望能對初學者進行MATLAB編程訓練提供一些可供參考的材料,并起到一定的指導和激勵作用,進而為MATLAB編程入門打下好的基礎.關鍵字 算法設計;程序調試與測試;程序優(yōu)化;循環(huán)控制1 算法與程序1.1 算法與程序的關系算法被稱為程序的靈魂,因此在介紹程序之前應先了解什么是算法.所謂算法就是對特定問題求解步驟的一種描述.對于一個較復雜的計算或是數(shù)據(jù)處理的問題,通常是先設計出在理論上可行的算法,即程序的操作步驟,然后再按照算法逐步翻譯成相應的程序語言,即計算機可識別的語言.所謂程序設計,就是使用在計算機上可執(zhí)行的程序代碼來有效的描述用于解決特定問題算法的過程.簡單來說,程序就是指令的集合.結構化程序設計由于采用了模塊分化與功能分解,自頂向下,即分而治之的方法,因而可將一個較復雜的問題分解為若干子問題,逐步求精.算法是操作的過程,而程序結構和程序流程則是算法的具體體現(xiàn).1.2 MATLAB語言的特點MATLAB語言簡潔緊湊,使用方便靈活,庫函數(shù)極其豐富,其語法規(guī)則與科技人員的思維和書寫習慣相近,便于操作.MATLAB程序書寫形式自由,利用其豐富的庫函數(shù)避開繁雜的子程序編程任務,壓縮了很多不必要的編程工作.另外,它的語法限制不嚴格,程序設計自由度大.其最大的特點是以矩陣運算為最強,而數(shù)值的矩陣化又為運算和處理提供了方便.除此之外,MATLAB還有著非常強大的繪圖功能.1.3 MATLAB程序設計練習MATLAB有著豐富的庫函數(shù),一般情況下應了解并學會使用一些常用的庫函數(shù),至少應熟悉函數(shù)庫中都有哪些常用函數(shù),當需要時可以現(xiàn)學現(xiàn)用.或者能對一些經典函數(shù)做一定的改造,以達到解決某一特定問題的目的.但,在大多情況下還需要自己編寫程序去處理形形色色的問題.下面就先從一些較簡單的程序入手來熟悉MATLAB的編程方式.例1 一個分類統(tǒng)計函數(shù)的設計(分類統(tǒng)計_1)編寫一個函數(shù),統(tǒng)計出一組有序(按升序或降序排列)數(shù)字中每種數(shù)字的個數(shù),并返回數(shù)字種類數(shù).分析:設待統(tǒng)計數(shù)組為x,因為x有序,所以在設計算法時應抓住這個特點.若用s1記錄已統(tǒng)計出的數(shù)字,則,在對x中的數(shù)字進行遍歷時,每次只需讓x(i)與s1中的最后一個數(shù)字進行比較就可以了,若相等,則對應計數(shù)器加1,若不等,則說明測到新數(shù),應開辟新的存儲單元.其算法程序如下:function s,k=FLTJ_1(x) %x為待統(tǒng)計的一組有序數(shù),返回值s為2列的數(shù)組,%第一列為不同種類的數(shù)字,第二列為對應數(shù)字的個%數(shù),k記錄統(tǒng)計出的數(shù)字種類數(shù)目n=length(x); s1=x(1); % s1記錄測到的新數(shù)字,給其賦初值為x的第一個數(shù)字s2=1; % s2記錄s1中每個數(shù)字的個數(shù),賦初值為x(1)的初始個數(shù)1k=1; % k記錄已統(tǒng)計出的數(shù)字種類數(shù),初值賦為1for i=2:n % 從第2項開始遍歷數(shù)組x if x(i)=s1(end) % 如果x(i)與已測出的最后1個數(shù)字相同, s2(end)=s2(end)+1; % 則對應的計數(shù)器加1 else % 否則,則說明測到新數(shù)字 s1=s1;x(i); % 將此新數(shù)并入s1,s2=s2;1; %對應的計數(shù)器為1 k=k+1; % 同時k值加1 endends=s1,s2; % 將s1與s2拼接成一個兩列的數(shù)組s程序運行如下(“”代表回車,下同.) x=1,2,2,3,3,4,5,5; s,k=FLTJ_1(x) s = 1 1 2 2 3 2 4 1 5 2k = 5例2 一個數(shù)字游戲的設計有這樣一個數(shù)字游戲:在一個2010的矩陣中,099這100個數(shù)順序排列在奇數(shù)列中(每20個數(shù)組成一列),另有100個圖案排列在偶數(shù)列中,這樣每個數(shù)字右邊就對應一個圖案.你任意想一個兩位數(shù)a,再讓a減去它的個位數(shù)字與十位數(shù)字之和得到一個數(shù)b,然后,在上述矩陣的奇數(shù)列中找到b,將b右邊的圖案記在心里,最后點擊指定的按鈕,你心里的那個圖案將被顯示.下面我們就來編寫程序模擬一下這個小游戲,以0,1之間的小數(shù)代替矩陣中的圖案,由MATLAB程序實現(xiàn)如下:程序I% “測心術”游戲format shorta=1;t=0;while a a1=rand(100,1); k=3;s=; while k1再試一次n); end使用說明:運行程序I生成一個2010的矩陣s,你任意想一個兩位數(shù)a,按照上面所說的步驟操作,然后在s的奇數(shù)列中找到b,將b右邊的小數(shù)記在心里,再調用程序II,則返回你所記下的那個小數(shù).(運行演示略)原理說明:設任意一個兩位數(shù)a=10+,則a-(+)=9=b,所以b一定是9的倍數(shù),且只可能在9到81之間.明白了這一點,上面程序中的各種設置就一目了然了.例3 折半查找算法要從一個數(shù)組x中找到一個指定的數(shù)a,通常的做法是從x的第一個數(shù)開始順序查找.如果x是一個無序的數(shù)組,的確沒有比順序查找更好的方法了,但如果x有序,設計查找算法時就要充分利用這已有的規(guī)律,折半查找就是針對有序數(shù)組進行查找的一種效率較高的方法.對于一個維數(shù)組,折半查找最多比較次數(shù)為,而順序查找的平均比較次數(shù)為.寫一個算法:在數(shù)組x中查找數(shù)字a,其中x是一個元素各異并按升序排列的一維數(shù)組.若找到a,則返回a在x中的位置,若a不在x中則返回“找不到”.折半查找算法程序如下:function s= BinarySearch (x,a) %折半查找法,x是按升序排列的%一維數(shù)組,a是要查找的數(shù)n=length(x);sign=0; %用sign標記是否查找成功,賦初值為假,當查找成功時其值為真top=1;bott=n; %查找區(qū)間端點下標,top為“頂”,bott為“底”if ax(n) %當a比x的最小值小或比x的最大值大時,返回找不到此數(shù), s=The number is not found; %并終止程序,否則在x的內部查找a return; else while(sign=0)&(top=bott) mid=fix(bott+top)/2); %求中位數(shù)并取整 if a=x(mid) %若找到a s=mid; %記錄它在x中的下標, sign=1; %并置標志變量為真 elseif a x=1 3 4 6 8 9 12 15; s= BinarySearch (x,6) s = 4 s= BinarySearch (x,7) s =The number is not found例4 對答卷中選擇題的初步統(tǒng)計函數(shù)當做完一項問卷調查后,或舉行完一次考試后,在對答卷中選擇題的做答情況做統(tǒng)計分析時,需要知道每個選擇題中每個選項的被選次數(shù)及所占的百分比.現(xiàn)假設選擇題只有4個選項(A,B,C,D),某些題目允許多選,但不得選多于2項.(如果題目的選項或可選項增加的話,方法類似.)4個選項分別用1,2,3,4表示(若選擇AB,則表示為12),缺選時用0表示.請編程序統(tǒng)計每個題目中每個選項的被選次數(shù)及所占的百分比.分析:若一共有n個題目,可用兩個4n的矩陣分別表示每個選項的被選次數(shù)與所占的百分比,在統(tǒng)計的過程中用數(shù)組分別為每個題目中的每個選項計數(shù).MATLAB程序如下:function s1,s2=TongJi1(A) %A為答卷結果的數(shù)據(jù),返回值s1,s2分別為每個%選項的被選次數(shù)與所占的百分比m,n=size(A);s1=;s2=;D=ones(1,n).*m; %D記錄每個題目中每個選項被選次數(shù)總和,%給每個元素賦初值為mfor j=1:n B=zeros(4,1); %B為計數(shù)器,記錄每個題目中的每個選項的被選次數(shù) for i=1:m t=A(i,j); if t=0 %缺選時,在該題的總數(shù)記錄中減1 D(j)=D(j)-1; elseif t10 %只選一項時,在該項的計數(shù)器上加1 B(t)=B(t)+1; else %當選兩項時,需分離數(shù)字,再讓每項的計數(shù)器加1,%同時該題目的各項被選次數(shù)總和加1 t1=floor(t/10); t2=t-t1*10; B(t1)=B(t1)+1; B(t2)=B(t2)+1; D(j)=D(j)+1; endend s1=s1,B; %組合矩陣 B1=B./D(j); %求百分比 s2=s2,B1;end附錄中表1是一個有20個學生作答記錄的數(shù)據(jù),若記該數(shù)據(jù)矩陣為A,調用上面的程序運行如下:?s1,s2=TongJi1(A) s1 = 3 8 0 0 2 0 0 2 8 5 5 7 12 1 7 4 4 4 5 7 2 13 7 8 4 2 9 5 3 5 5 5s2 = 0.1579 0.4211 0 0 0.1053 0 0 0.1053 0.4211 0.2632 0.2632 0.3684 0.6316 0.0526 0.3684 0.2105 0.2105 0.2105 0.2632 0.3684 0.1053 0.6842 0.3684 0.42110.2105 0.1053 0.4737 0.2632 0.1579 0.2632 0.2632 0.2632例5 列主元Gauss消去法解方程組列主元Gauss消去法是指在解方程組時,未知數(shù)順序消去,在要消去的那個未知數(shù)的系數(shù)中找按模最大者作為主元.完成消元后,系數(shù)矩陣化為上三角形,然后在逐步回代求解未知數(shù).列主元Gauss消去法是在綜合考慮運算量與舍人誤差控制的情況下一種較為理想的算法.其算法描述如下:1.輸入系數(shù)矩陣A,右端項b2.測A的階數(shù)n,對k=1,2,n-1循環(huán)a) 按列主元保存主元所在行的指標.b) 若,則系數(shù)矩陣奇異,返回出錯信息,計算停止;否則,順序進行.c) 若則轉向d);否則換行 ,d) 計算乘子,e) 消元:3.回代 ,方程組的解X存放在右端項b中.MATLAB程序如下:function s=LZYgauss(A,b) % 列主元高斯消去法:A為系數(shù)矩陣,b為右端項n=length(A(:,1); % 測量A一行的長度,得出nfor k=1:n-1 % 循環(huán),消元 a,t=max(abs(A(k:n,k);% 尋找最大值(記為a) p=t+k-1; % 最大值所在的行記為p if a=0 % 若a=0,則A為奇異陣,返回出錯信息 error(A is a bizarre matrix); else %若a不等于0,換行 t1=A(k,:); A(k,:)=A(p,:); A(p,:)=t1; t2=b(k);b(k)=b(p);b(p)=t2; A,b for j=k+1:n % 消元過程 m=A(j,k)/A(k,k); A(j,:)=A(j,:)-m.*A(k,:); b(j)=b(j)-m*b(k); end endendA,bb(n)=b(n)/A(n,n); % 回代過程for i=1:n-1 q=(b(n-i)-sum(A(n-i,n-i+1:n).*b(n-i+1:n)/A(n-i,n-i); b(n-i)=q;ends=b; % 解放在s中程序運行(略)2 程序的的調試與測試程序調試的目的是檢查程序是否正確,即程序能否順利運行并得到預期結果.在運行程序之前,應先設想到程序運行的各種情況,測試在各種情況下程序是否能正常運行.對初學編程的人來說,很難保證所編的每個程序都能一次性運行通過,而大多情況下都需要對程序進行反復的調試之后才能正確運行.所以,不要害怕程序出錯,要時時準備著去查找錯誤,改正錯誤.2.1 程序常見的錯誤類型2.1.1 易犯的低級錯誤a 輸入錯誤常見的輸入錯誤除了在寫程序時疏忽所導致的手誤外,一般還有:在輸入某些標點時沒有切換成英文狀態(tài);表循環(huán)或判斷語句的關鍵詞 “for”, “while”,“if”的個數(shù)與“end”的個數(shù)不對應(尤其是在多層循環(huán)嵌套語句中);左右括號不對應等.b 對程序的修改不徹底導致的錯誤由于之前對程序中的某些部分(如變量或符號名稱)做了修改,但后面又有用到它們或與之有關系的地方卻沒有做相應的修改.2.1.2 語法錯誤不符合MATLAB語言的規(guī)定,即為語法錯誤.例如在用MATLAB語句表示數(shù)學式“”時,不能直接寫成“k1=x=k2”,而應寫成“k1=x&x x=3,2,2,4,5,4; s,k=FLTJ_2(x) s = 3 1 2 2 2 1 4 2 5 1 4 1k = 6輸出結果顯然是不對的,考慮一下問題出在哪了?事實上,當?shù)诙€“for”循環(huán)中的判斷語句第一次不成立時并不能立即得出“測到新數(shù)”的結論,只有在對j的循環(huán)結束(即循環(huán)進行到k)時,若判斷語句仍不成立才能說明測到了新數(shù).因此,應將第二個“for”循環(huán)內的判斷語句修改如下(注意觀察虛線框內的修改部分): if x(i)=s1(j) s2(j)=s2(j)+1; break; elseif j=k %對j的循環(huán)進行到k時判斷語句仍不成立, %則說明測到新數(shù),置flag為1flag=1; end其實,還可以將標志變量flag換一種方式使用,將程序中的循環(huán)改寫如下:for i=2:n % 從第2項開始遍歷數(shù)組x flag=0; % 標示變量,標記是否測到新數(shù)字,此趟遍歷開始前,其值應為假 for j=1:k if x(i)=s1(j) % 如果x(i)與已測出的第j個數(shù)字相同, s2(j)=s2(j)+1; % 則對應的計數(shù)器加1, flag=1; % 同時置flag為1,并結束此次遍歷 break; end endif flag % 當flag仍為假時,即測到新數(shù)字 s1=s1;x(i); s2=s2;1; k=k+1; end通過分析你會發(fā)現(xiàn),這兩種用法實際上是等效的.其實,此程序無需使用標志變量,可將循環(huán)直接寫成如下形式.for i=2:n for j=1:k if x(i)=s1(j); s2(j)=s2(j)+1; break; elseif j=k s1=s1;x(i); s2=s2;1; k=k+1; end endend修改后的程序運行如下: x=3,2,2,4,5,4; s,k=FLTJ_2(x) s = 3 1 2 2 4 2 5 1k = 4請思考一下,第一個”if”條件下如果沒有”break”程序能否運行正確?想一想為什么?2.1.4 運行錯誤程序的運行錯誤通常包括不能正常運行和運行結果不正確,出錯的原因一般有: 數(shù)據(jù)不對,即輸入的數(shù)據(jù)不符合算法要求(見下例). 輸入的矩陣大小不對,尤其是當輸入的矩陣為一維數(shù)組時,應注意行向量與列向量在使用上的區(qū)別. 程序不完善,只能對“某些”數(shù)據(jù)運行正確,而對“另一些”數(shù)據(jù)則運行錯誤,或是根本無法正常運行,這有可能是算法考慮不周所致.看下面這個例子例 在用1.3例3中的折半查找程序做查找時輸入一組命令運行如下: x=3 5 2 4 7 6 11; s= BinarySearch (x,4) s = 4 s=BinarySearch(x,5) s =The number is not found分析:第一次對4的查找返回了正確的結果,但第二次對5進行查找時卻出了錯.原因是數(shù)組x并非有序數(shù)組,不符合折半查找的要求(要求數(shù)組為升序排列).對4的查找正確,也僅僅是一個巧合而已,恰好在第一次“折半”中找到了它,而對5的查找就會在4的右邊進行,自然是找不到的.2.2 程序查錯的若干方法 先查看程序中有無輸入錯誤. 善于利用程序運行時給出的出錯信息來查找錯誤. 檢查算法是否有誤. 在一些適當?shù)奈恢蔑@示一些變量的值,看其運行情況,如果發(fā)現(xiàn)前面的運行正確則繼續(xù)向后開設顯示變量觀察運行情況. 將循環(huán)控制變量的值設成某個常數(shù),如將原來的“i=1:n”,改成“i=k”(k為1n之間的一個數(shù)),再看其運行情況.下面來看一個例子,仍以折半查找算法為例.例 如果在編寫折半查找算法的程序時將“while”循環(huán)下的“mid=fix(bott+top)/2)”語句寫成了“mid=(bott+top)/2”,看一下其運行情況: x1=1 3 4 6 8 9 12; s= BinarySearch(x1,8) s = 5 s= BinarySearch(x1,3) s = 2 x2=1 3 4 6 8 9 12 15; s=BinarySearch(x2,8) ? Attempted to access x2(4.5); index must be a positive integer or logical.Error in = BinarySearch at 12 if a=x(mid) %若找到a通過上面的運行情況發(fā)現(xiàn),在x1中能正確查找,但在x2中查找時卻返回了出錯信息,說是“試圖訪問x2(4.5),下標必須為正整數(shù)或合乎常理”,因為數(shù)組x2的長度為8,在第1次“折半”時得到 (1+8)/2=4.5=mid,而數(shù)組的下標必須為整數(shù),所以出錯.事實上,當數(shù)組x的長度是偶數(shù)時,第1次“折半查找”就無法進行,因為(1+)/2不是整數(shù).當是奇數(shù)時,至少能進行一次,特別地當=-1(k=1,2,3,)時,對x中所有元素的查找都能正常進行(分析一下,為什么?),例如上面的x1中恰有7個元素,為k=3時的情形.所以,這里還要強調的是:在對程序進行測試時,當你有幸輸入了某些特殊的數(shù)據(jù)(比如,在此例中輸入數(shù)組x的長度恰好為-1)發(fā)現(xiàn)運行正確,不要就此以為程序已經正確無誤了.再回到原來的話題,通過上面的測試發(fā)現(xiàn)了問題所在,為了使程序對所有的都能正常運行,應加入對“(bott+top)/2”取整的操作,函數(shù)“fix”的作用是向0方向取整,也可使用“floor” (朝負無窮大方向取整).3 算法與程序的優(yōu)化如果一個程序通過各種測試都能正常運行并得到正確的結果,換句話說,這個程序沒有任何錯誤,就能說它已經“完美”了嗎?答案是:不一定.下面就來說一下有關算法和程序的優(yōu)化問題.在設計算法和程序時往往容易只去注重算法和程序的可行性,而忽視對算法和程序的優(yōu)化.當遇到一些問題需要龐大的計算量時,如果算法或程序不夠優(yōu)化,則難以在有限的時間內完成計算.(這一點我深有體會.)另外,雖然MATLAB有強大的計算功能,但這也給它帶來了自身的缺點,它和其他高級程序語言相比,程序的執(zhí)行速度較慢,這就更需要去注重算法的優(yōu)化問題了.即使對于那些不需要很大計算量的程序也要盡量做到優(yōu)化,因為這體現(xiàn)了一個人的編程素質.所以要養(yǎng)成這樣一種好的習慣,提高程序的質量.程序的優(yōu)化本質上也是算法的優(yōu)化,如果一個算法描述的比較詳細的話,它幾乎也就指定了程序的每一步.若算法本身描述的不夠詳細,在編程時會給某些步驟的實現(xiàn)方式留有較大空間,這樣就需要找到盡量好的實現(xiàn)方式以達到程序優(yōu)化的目的,但一般情況下認為算法是足夠詳細的.如果一個算法設計的足夠“優(yōu)”的話,就等于從源頭上控制了程序走向“劣質”.算法優(yōu)化的一般要求是:不僅在形式上盡量做到步驟簡化,簡單易懂,更重要的是能用最少的時間復雜度和空間復雜度完成所需計算.包括巧妙的設計程序流程,靈活的控制循環(huán)過程(如及時跳出循環(huán)或結束本次循環(huán)),較好的搜索方式及正確的搜索對象等,以避免不必要的計算過程.例如在判斷一個整數(shù)是否是素數(shù)時,可以看它能否被/2以前的整數(shù)整除,而更快的方法是,只需看它能否被以前的整數(shù)整除就可以了.再比如,在求與之間的所有素數(shù)時跳過偶數(shù)直接對奇數(shù)進行判斷,這都體現(xiàn)了算法優(yōu)化的思想.下面通過幾個具體的例子來體會其中所包含的優(yōu)化思想.例1 冒泡排序算法冒泡排序是一種簡單的交換排序,其基本思想是兩兩比較待排序記錄,如果是逆序則進行交換,直到這個記錄中沒有逆序的元素.該算法的基本操作是逐趟進行比較和交換.第一趟比較將最大記錄放在xn的位置.一般地,第i趟從x1到xn-i+1依次比較相鄰的兩個記錄,將這n-i+1個記錄中的最大者放在了第n-i+1的位置上.其算法程序如下:function s=BubbleSort(x) % 冒泡排序,x為待排序數(shù)組n=length(x);for i=1:n-1 % 最多做n-1趟排序 flag=0; % flag為交換標志,本趟排序開始前,交換標志應為假 for j=1:n-i % 每次從前向后掃描,j從1到 n-i if x(j)x(j+1) % 如果前項大于后項則進行交換 t=x(j+1); x(j+1)=x(j); x(j)=t; flag=1; % 當發(fā)生了交換,將交換標志置為真 end end if (flag) % 若本趟排序未發(fā)生交換,提前終止算法 break; endends=x;說明:本程序通過使用標志變量flag來標志在每一趟排序中是否發(fā)生了交換,若某趟排序中一次交換都沒有發(fā)生則說明此時數(shù)組已經為有序(正序),應提前終止算法(跳出循環(huán)).若不使用這樣的標志變量來控制循環(huán)往往會增加不必要的計算量.例2 公交線路查詢問題設計一個查詢算法,給出一個公交線路網(wǎng)中從起始站s1到終到站s2之間的最佳線路.其中一個最簡單的情形就是查找直達線路,假設相鄰公交車站的平均行駛時間(包括停站時間)為3分鐘,若以時間最少為擇優(yōu)標準,請在此簡化條件下完成查找直達線路的算法,并根據(jù)附錄數(shù)據(jù)(數(shù)據(jù)1),利用此算法求出以下起始站到終到站之間的最佳路線. 242105 11753 179201 16162分析:為了便于MATLAB程序計算,應先將線路信息轉化為矩陣形式,導入MATLAB(可先將原始數(shù)據(jù)經過文本導入Excel).每條線路可用一個一維數(shù)組來表示,且將該線路終止站以后的節(jié)點用0來表示,每條線路從上往下順序排列構成矩陣A.此算法的核心是線路選擇問題,要找最佳線路,應先找到所有的可行線路,然后再以所用的時間為關鍵字選出用時最少的線路.在尋找可行線路時,可先在每條線路中搜索s1,當找到s1則接著在該線路中搜索s2,若又找到s2,則該線路為一可行線路,記錄該線路及所需時間,并結束對該線路的搜索.另外,在搜索s1與s2時若遇到0節(jié)點,則停止對該數(shù)組的遍歷.下面是實現(xiàn)這一算法的一個程序,看它是否做到了足夠的優(yōu)化.function L,t=DirectLineSearch(s1,s2,A) %A為線路信息矩陣,s1,s2分別%為起始站和終到站.返回值L為最佳線路,t為所需時間m,n=size(A);L1=;t1=; % L1記錄可行線路,t1記錄對應線路所需時間for i=1:m for j=1:n if A(i,j)=s1 %若找到s1,則從下一站點開始尋找s2 for k=j+1:n if A(i,k)=0 %若此節(jié)點為0,則跳出循環(huán) break; elseif A(i,k)=s2 %若找到s2,記錄該線路及所需時間,%然后跳出循環(huán) L1=L1,i; t1=t1,(k-j)*3; break; end end end endendm1=length(L1); %測可行線路的個數(shù)if m1=0 %若沒有可行線路,則返回相應信息 L=No direct line; t=Null;elseif m1=1L=L1;t=t1; %否則,存在可行線路,用L存放最優(yōu)線路,t存放最小的時間else L=L1(1);t=t1(1); %分別給L和t賦初值為第一條可行線路和所需時間 for i=2:m1 if t1(i)t %若第i條可行線路的時間小于t,L=i; %則給L和t重新賦值, t=t1(i); elseif t1(i)=t %若第i條可行線路的時間等于t, L=L,L1(i); %則將此線路并入L end endend首先說明,這個程序能正常運行并得到正確結果,但仔細觀察之后就會發(fā)現(xiàn)它的不足之處:一個是在對j的循環(huán)中應先判斷節(jié)點是否為0,若為0則停止向后訪問,轉向下一條路的搜索.另一個是,對于一個二維的數(shù)組矩陣,用兩層(不是兩個)循環(huán)進行嵌套就可以遍歷整個矩陣,得到所有需要的信息,而上面的程序中卻出現(xiàn)了三層循環(huán)嵌套的局面.其實,在這種情況下,倘若找到了s2,本該停止對此線路節(jié)點的訪問,但這里的“break”只能跳出對k的循環(huán),而對該線路數(shù)組節(jié)點的訪問(即對j的循環(huán))將會一直進行到n,做了大量的“無用功”.為了消除第三層的循環(huán)能否對第二個循環(huán)內的判斷語句做如下修改: if A(i,j)=s1 continue; if A(i,k)=s2 L1=L1,i; t1=t1,(k-j)*3; break; end end這種做法企圖控制流程在搜到s1時能繼續(xù)向下走,搜索s2,而不用再嵌套循環(huán).但這樣卻是行不通的,因為即使s1的后面有s2,也會被先被“if A(i,j)=s1”攔截,“continue”后的語句將不被執(zhí)行.所以,經過這番修改后得到的其實是一個錯誤的程序.事實上,若想消除第三層循環(huán)可將這第三層循環(huán)提出來放在第二層成為與“j”并列的循環(huán),若在對j的循環(huán)中找到了s1,可用一個標志變量對其進行標志,然后再對s1后的節(jié)點進行訪問,查找s2.綜上,可將第一個“for”循環(huán)內的語句修改如下: flag=0; % 用flag標志是否找到s1,為其賦初值為假 for j=1:n if A(i,j)=0 %若該節(jié)點為0,則停止對該線路的搜索,轉向下一條線路 break; elseif A(i,j)=s1 %否則,若找到s1,置flag為真,并跳出循環(huán) flag=1; break; end end if flag %若flag為真,則找到s1,從s1的下一節(jié)點開始搜索s2 for k=j+1:n if A(i,k)=0 break; elseif A(i,k)=s2 %若找到s2,記錄該線路及所需時間,%然后跳出循環(huán) L1=L1,i; t1=t1,(k-j)*3; break; end endend若將程序中重疊的部分合并還可以得到一種形式上更簡潔的方案:q=s1; %用q保存s1的原始值for i=1:m s1=q; %每一次給s1賦初值 p=0; %用p值標記是否搜到s1或s2 k=0; %用k記錄站點差 for j=1:n if A(i,j) break; elseif A(i,j)=s1 %若搜到s1,之后在該線路上搜索s2,并記p為1 p=p+1; if p=1 k=j-k; s1=s2; elseif p=2 %當p值為2時,說明已搜到s2,記錄相關信息, L1=L1,i; t1=t1,3*k;%同時s1恢復至原始值,進行下一線路的搜索 break; end end endend程序運行如下:?L,t=DirectLineSearch(242,105,A) L = 8t = 24?L,t=DirectLineSearch(117,53,A) L = 10t = 15?L,t=DirectLineSearch(179,201,A) L = 7 14t = 27?L,t=DirectLineSearch(16,162,A) L =No direct linet =Null注:在設計算法或循環(huán)控制時,應注意信息獲取的途徑,避免做無用的操作步驟.如果上面這個程序不夠優(yōu)化,它將為后續(xù)轉車的程序造成不良影響.例3 分類統(tǒng)計_3 :統(tǒng)計一組數(shù)字中每種數(shù)字的個數(shù),并使統(tǒng)計出的數(shù)字升序排列.分析:事實上要解決這個問題,完全可以先利用“分類統(tǒng)計_2”進行統(tǒng)計后再用冒泡排序等排序算法對已統(tǒng)計出的數(shù)字進行排序即可,但,要是能在統(tǒng)計的過程中又同時進行排序操作勢必會比前者的計算量更少.如此,可采用“折半插入排序”的方法完成排序,即,將后續(xù)統(tǒng)計出的數(shù)字用插入排序的方法插入到已統(tǒng)計出的有序數(shù)組,而插入位置則用折半查找的方式尋找,若測到的不是新數(shù)字只需使其對應的計數(shù)器加1.下面看這個算法的程序:function s,k=FLTJ_3(x) % 統(tǒng)計數(shù)組x中每種數(shù)字的個數(shù),將統(tǒng)計出的數(shù)字% 按升序排列n=length(x);s1=x(1);s2=1; % s1記錄統(tǒng)計出的數(shù)字,s2記錄對應數(shù)字個數(shù),并為它們% 分別賦初值為:x的第1個數(shù)字,個數(shù)為1k=1; % k記錄已統(tǒng)計出的數(shù)字個數(shù)for i=2:n %從x的第2個元素開始遍歷if x(i)s1(k) %若x(i)比s1(k)小,應放在s1(k)后面 s1=s1;x(i); s2=s2;1; k=k+1;else %否則,應在s1內部查找x(i)或其插入位置 flag=0; %標志變量,標志是否在s1中找到x(i) top=1;bott=k; %查找區(qū)間下標 while (flag=0&top=bott) mid=fix(bott+top)/2); if x(i)=s1(mid) %若在s1中找到x(i), s2(mid)=s2(mid)+1; %讓其對應計數(shù)器加1 flag=1; %并置標志變量為真 elseif x(i) x=4 5 3 4 5 7 5 1 2 3 8 3 2 1; s,k=FLTJ_3(x) s = 1 2 2 2 3 3 4 2 5 3 7 1 8 1k = 7評論:此程序除涉及前面例子中的統(tǒng)計方法外,還用到了插入排序及折半查找的思想,因此它著實能鍛煉一個人整合各種算法的能力,即將各種算法的思想整合到一個程序中以解決特定的問題,并在這個過程中巧妙利用已有信息(或在前面的計算中所得到的信息),做到程序優(yōu)化.事實上,對于編程能力的訓練,往往是先從解決一些較為簡單問題入手,然后通過對這些問題修改某些條件,增加難度等不斷的進行摸索,在不知不覺中自己的編程能就已經被提升到了一個新的高度.4 有關循環(huán)控制的討論幾乎所有實用的程序都包含循環(huán)控制,它和順序

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論