日常工作中,處理數據難免會遇到遍歷,for循環可能是我們用的比較多的了。本節就來探討下for語句嵌套循環的性能,猜想下面兩個語句的性能。
語句1
for ( i= 0; i < 1000000; i++)
{ for (j =0; j < 100; j++) { expression; }
}
語句2
for ( i= 0; i < 100; i++)
{ for (j =0; j < 1000000; j++) { expression; }
}
乍一看,感覺兩個嵌套循環執行的次數都是一樣的,那麼他們的時間復雜度是一樣的嗎?讓我們來分析下,語句1外層循環執行了1000000次,內層循環執行了1000000*100次,而語句2外層循環執行了100次,內層循環也執行了1000000*100次。那麼,既然內層執行的次數都一樣,外層是不是執行的越少越好呢?讓我們寫代碼認證下。
驗證代碼
static void Main(string[] args) { Stopwatch sw = new Stopwatch(); sw.Start(); for (int i = 0; i < 1000000; i++) { for (int j = 0; j < 100; j++) { // expression; } } sw.Stop(); Console.WriteLine(sw.ElapsedMilliseconds); sw.Reset(); sw.Start(); for (int i = 0; i < 100; i++) { for (int j = 0; j < 1000000; j++) { // expression; } } sw.Stop(); Console.WriteLine(sw.ElapsedMilliseconds); }
驗證截圖
得出結論,對於for語句的嵌套循環,總循環次數相等,外層循環越小越好。個人拙見,工作中具體情況具體對待...
補充總結(2月3日)
上文的描述給大家展現的都是現象,並沒有告訴大家事物的本質。(@Sunday*)Sunday*告訴我說“是因為減少了對int j=0的賦值操作,這些會有一定的性能上的消耗,但這種優化不是本質上的性能提升!”,於是引發了我更深層次的思考。其實,控制外層循環次數越小,我們可以發現i自增的次數少了,i<100的判斷次數少了,以及內層循環中的int j=0賦值的次數也少了,自然而然性能就得到了提升。
Sunday*說的很對:使用for應盡量避免裡面創建對象,減少循環次數,這樣才能達到優化;而我得出的結論:對於for語句的嵌套循環,總循環次數相等,外層循環越小越好。兩者都是正確的。代碼是死的,人是活的,人得靈活駕馭代碼,具體情況具體對待。
最後,我不否認這種優化對性能提升不了多少,但是,假如我遇到了本文所提的情況,我必須得本能得寫出最優代碼,這也是我研究的目的所在。