一般,要分析的最重要的資源就是運行時間。有幾個因素影響着程序的運行時間。有些因素(如使用編譯器和計算機)顯然超出了任何理論模型的範疇,所以,雖然它們是重要的,可是咱們在這裏仍是不能考慮它們。剩下的主要因素是所使用的算法以及對該算法的輸入。算法
典型的情形是,輸入的大小是主要的考慮方面。咱們定義兩個函數Tavg(N)和Tworst(N),分別爲算法對於輸入量N所花費的平均運行時間和最壞狀況的運行時間。顯然,Tavg(N)<=Tworst(N)。編程
若是存在多於一個的輸入,那麼這些函數可用有多於一個的變量。數組
偶爾也分析一個算法的最好情形的性能。不過,一般這沒有什麼重要意義,由於它不表明典型的行爲。平均情形性能經常反映典型的行爲,而最壞的性能則表明對任何可能輸入的性能一種保證。還要注意,雖然在這一章咱們分析的是Java程序,但所獲得的界其實是算法的界而不是程序的界。程序是算法以一種特殊編程語言的實現,程序設計語言的細節幾乎老是不影響大於O的答案。若是一個程序比算法分析提出的速度慢得多,那麼可能存在低效率的實現。這在相似C++的語言中很廣泛,好比,數組可能看成總體而被漫不經心的拷貝,而不是由引用來傳遞。無論怎麼說,這在Java中也可能出現。緩存
通常來講,若是沒有相反的指定,則所須要的量是最壞狀況的運行時間。其緣由之一是它對全部的輸入提供了一個界限,包括特別壞的輸入,而平均狀況分析不提供這樣的界。另外一個緣由是平均狀況的界計算起來一般要困可貴多。在某些狀況下,「平均」的定義可能影響分析的結果。(例如,什麼是下屬問題的平均輸入?)編程語言
做爲一個例子,咱們將在下一節考慮下述問題:函數
例如:對於輸入-2,11,-4,13,-5,-2,答案爲20(從A2到A4) 。性能
這個問題之因此有吸引力,主要是由於存在求解它的不少算法,而這些算法的性能又差別很大。咱們將討論求解該問題的四種算法。這四種算法在某臺計算機上(到底是哪一臺具體的計算機並不重要)的運行時間。如圖:設計
在表中有幾個重要的狀況值得注意。對於小量的輸入,這些算法都在眨眼之間完成,所以若是隻是小量輸入的情形,那麼花費大量的努力去設計聰明的算法恐怕就太不值得了。blog
另外一方面,近來對於重寫那些再也不合理的基於小輸入量假設而在五年之前編寫的程序確實存在巨大的市場。如今看來,這些程序太慢了,由於它們用的是一些低劣的算法。對於大量的輸入,算法4顯然是最好的選擇(雖然算法3也能夠用)。內存
其次,表中所給的時間不包括讀入數據所須要的時間。對於算法4,僅僅從磁盤讀入數據所用的時間極可能在數量級上比求解上述問題所須要的時間還要大。這是許多有效算法的典型特色。數據的讀入通常是個瓶頸;一旦數據讀入,問題就會迅速解決。可是,對於低效率的算法狀況就不一樣了,它必然要佔用大量的計算機資源。所以只要可能,使得算法足夠有效而不至成爲問題的瓶頸是很是重要的。
注意到具備線性複雜度的算法4表現很好,當問題的規模增加了十倍的時候,其運行的時間也增加十倍。而具備平方複雜度的算法2就不行了,十倍的規模增加致使運行時間大於有百倍(10的2次方)的增加。而立方級複雜度的算法1的運行時間則由千倍(10的3次方)的增加。對於N=100000,咱們能夠預期算法1將花費近乎90000秒或一天的時間。相似地,咱們可預期算法2用大約333秒來完成N=1000000。然而,算法2也可能花費更多的時間,由於在現代計算機中,內存存取N=1000000可能比處理N=100000要慢,這取決於內存緩存的大小。
再看圖:
左圖指出了四種算法運行時間的增加率。儘管該圖只包含N從10到100的值,可是相對增加率仍是很明顯的。雖然O(NlogN)算法的圖看起來是線性的,可是用直尺的邊(或是一張紙)容易驗證它並非直線。雖然O(N)算法的圖看似直線,但這只是由於對於小的N值其中的常數項大於線性項。右圖中更顯示對於更大值的性能。該圖明顯地代表,對於即便是適度大小的輸入量低效算法依然是多麼的無用。