时间复杂度和空间复杂度的故事
前言一
很多搞 iOS 開發的同學都沒有學過算法,有一些甚至沒有學過數據結構。在很多人的觀念中,算法和數據結構只是在面試的時候有用。
這些人的想法對嗎?在我看來,也對,也不對。
對于 iOS 開發來說,大多數時候都不需要算法和數據結構知識,但是如果你了解了算法和數據結構知識,在一些關鍵時候,這些知識會影響你的產品質量和開發效率。
很多人排斥學習這方面的知識,除了用得地方少之外,還有一個原因就是這部分知識比較難。
所以我打算寫一個輕松學習數據結構和算法的系列,結合 iOS 開發的故事,讓大家看看工作中有哪些地方會接觸到數據結構和算法。
這是本系列的第二篇,我們講講時間復雜度。
前言二
「時間復雜度」這個名稱對于非計算機專業的人絕對是一個重磅炸彈,一般在面試的時候,大家對于算法題都還是能想到一些可行的解法的。但是只要面試官一問起「時間復雜度」,好多非科班出身的同學就會馬上繳械投降了。
那么時間復雜度真的有那么重要嗎?它在實際工作中到底有什么用?我們來看看下面幾個故事。
故事一
我在公司里常常會指導一些 iOS 開發的新人,在我帶的 iOS 開發新人里面,有一個很聰明的女生,我們這里叫她「Liu 同學」吧。
Liu 同學有一次由于業務需要,得在 iOS 端做一個圖片裁剪的工作,圖片的內容是白底黑字,她需要寫算法把圖片周圍的空白部分裁剪掉,保留有字的部分。
因為邊緣的文字位置大概是知道的,所以她寫了一個二分的算法,從圖象的邊緣文字開始,用二分的方式來尋找邊界。當她和我討論的時候,我問了以下幾個問題:
-
這個圖片寬高大概是多少?她回答:寬度約是 600,高度約是 100。
-
二分的的區域大概是多少?她回答:因為邊緣的文字位置大概是知道的,所以二分的高度大概是 50,寬度 600。
于是,我告訴她,即使你完全暴力遍歷這個二分區域,也只需要檢查 600 * 50 = 30000 個點。對于計算機來說,這點運算量根本不值得花精力寫二分查找算法,她聽了恍然大悟。
很多時候,懂時間復雜度并不是讓你寫復雜的代碼,而是讓你避免寫復雜的代碼。
故事二
Redis 是一個優秀的服務器組件,你可以把它當緩存使用,也可以把它當作一個 Key/Value 內存數據庫來使用。由于它支持持久化,所以你也不用擔心內存中的數據丟失。
我有一次閱讀到了 Redis 的源碼,發現 Redis 在實現字典時選擇了一種名為 Skiplist 的數據結構,而不是被廣泛使用的紅黑樹。作者在被問到為什么選擇 Skiplist 時答到:「They are simpler to implement, debug, and so forth」。
所以,如果你了解時間復雜度,你就可以更有主見地,根據具體情況來做數據結構的選擇,而不是盲目聽信權威。
它對我產生的什么幫助呢?在我做移動端開發的時候,我發現移動端的業務場景處理的數據量都非常小,所以我就基于 SQLite 做了一個非常簡單的 Key/Value 存儲項目 YTKKeyValueStore ( https://github.com/yuantiku/YTKKeyValueStore ),我當然知道這里面有性能損失,但是我在開發之前,就能夠依據自己的數據結構經驗,判斷出這一點性能損失是能夠接受的。
故事三
我在高中的時候就對計算機產生了興趣,當時報名參加了學校的編程興趣班,并且參加過國家舉辦的 NOIP(全國青少年信息學奧林匹克聯賽)。當時的 NOIP 比賽需要大家的解題代碼不能運行時間過久,但是我當時一直不知道如何估計自己代碼的運行時間。
直到進入大學參加 ACM,才從培訓中了解到,可以用一些簡單的辦法的估計程序的運行時間,當時大家流傳著一秒鐘 大概等于「運行一千萬次循環」的時間估算方法。直到那時,我才真正對時間復雜度有了實用性上的認識。
當時做競賽題目有一些非常簡單的技巧:即根據題目給出的數據范圍來猜解法的時間復雜度。
舉個例子,比如一道題目的輸入是一個 A,這個 A 的范圍是 0 ~ 100 萬,那么在一秒鐘的時間限制下,你就只能設計 O(N) 時間復雜度以下的算法。因為如果你的算法復雜度是 O(N^2),那么運行時間肯定會超過一秒鐘。
在工作中,我們也會運用這些技巧來估計海量數據的處理時間。我還記得上周我們要在 Hive (一種分布式計算框架)中處理 5000 萬條數據,每條數據大概了 100K。我們設計的算法是 O(N) 時間復雜度的,然后我們簡單算了一下,如果不用 Hive 得話得運行好幾天,所以雖然麻煩一些,但我們就堅定地選擇了寫分布式計算程序。
我的估算過程如下:
因為算法是 O(N) 的,所以我們一共需要運算:5000 萬 x 100K 次,我們之前說了,1000 萬次運算大概要 1 秒,所以我們需要 500000 秒。一天大概是 8 萬秒,所以大概需要運行 6 天。
時間復雜度
在工作中,「時間復雜度」的用處在很多時候就像上面那些故事那樣,決定了我們用什么樣的代價來寫代碼。
我很早以前很天真的認為,寫代碼只需要考慮時間復雜度和空間復雜度就夠了。而大多數的權衡,都是在時間和空間上做選擇,一般時間復雜度優的,占用空間可能會更大一些。
但是我錯了,我們除了要考慮程序的運行時間、占用的內存外,還需要考慮該算法實現的成本!一個復雜的算法,在實現上是很可能寫出 Bug 的,而我們的工作時間有限,如果能夠寫簡單的算法就能搞定需求,為什么我們要寫復雜的代碼?
所以,時間復雜度真正的用處,是讓我們在寫代碼之前,就明白計算機運行這些代碼的時間。這樣,我們就能根據具體的業務需求,選擇最合適的寫代碼的方式,
理論
我們就實用的角度,簡單學習一下時間復雜度的理論吧。
時間復雜度是一個偏理論的概念,我們要描述它,首先需要了解它的描述方法,即:「大 O 表示法」。
「大 O 表示法」的準確的數學描述方式非常枯燥,我在這里就不貼出來湊字數了,其實大 O 表示法的意思挺簡單的,就是表示:隨著輸入的值變化,程序運行所需要的時間與輸入值的變化關系。如果不理解也沒關系,我們看兩行代碼就很容易懂了。
我們先看第一個代碼,這是一個函數,輸入一個數組,輸出這個數組里元數的和。
int count(int a[], int n) {int result = 0;for (int i = 0; i < n; ++i) {result += a[i];}return result; }對于這個程序來說,如果它處理 N 個元素求和所花的時間是 T,那么它處理 N 2 個元素的和所花的時間就是 T 2。所以隨著 N 變大,時間 T 的變大是與 N 呈「線性」關系的。
在時間復雜度中,我們用 O(N) 表示這種「線性」時間復雜度。
那是不是所有的函數都是「線性」關系的呢?我們再來看下面的程序。這是一個二分查找程序,從一個有序數組中尋找指定的值。
// 來自 https://en.wikipedia.org/wiki/Binary_search_algorithm int binary_search(int A[], int key, int imin, int imax) {if (imax < imin) {return KEY_NOT_FOUND;} else {int imid = midpoint(imin, imax);if (A[imid] > key)return binary_search(A, key, imin, imid - 1);else if (A[imid] < key)return binary_search(A, key, imid + 1, imax);elsereturn imid;} } ?對于這個程序來說,如果它處理 N 個元素求和所花的時間是 T,那么它處理 N 2 個元素的和所花的時間是多少呢?是 T 2 嗎?
如果頭腦算不清楚,我們可以拿實際的數字來實驗,二分查找每次(幾乎)可以去掉一半的候選數字。所以假如 N = 1024,那么它最多要找多少次呢?答案是 10 次,因為 2^10 = 1024,每次去掉一半,10 次之后就只剩下唯一一個元素了。
好,這個時候,如果元素的個數翻一倍,變成 2048 個,那么它最多要找多少次呢?相信大家都能算出來吧?答案是 11 次,因為 2 ^ 11 = 2048。
所以在這個例子中,輸入的元素個數雖然翻倍,但是程序運行所花的時間卻只增加了 1,我們把這種時間復雜度要叫「對數」時間復雜度,用 O(logN) 來表示。
除了剛剛講的「線性」時間復雜度和「對數」時間復雜度。我們還有以下這次常見的時間復度數。
「常數」時間復雜度,例如返回一個有序數組中的最小數,這個數因為始終在第一個位置,所以就不會受到數組大小的影響,無論數組多大,我們都可以在一個固定的時間返回結果。
「線性對數」時間復雜度,即 O(N*logN),這個復雜度比較常見,因為常見的高效的排序算法,都是這個時間復雜度,比如快速排序,堆排序,歸并排序等。
別的時間復雜度還有很多,每個具體的問題,我們都可以通過具體的分析,得到這個問題的時間復雜度。
運行時間估算
之前有一個故事中,我提到在 ACM 競賽中,大家常常簡單地把 1000 萬次運算當作一秒鐘的實際運行時間來估算。這個做法固然是從經驗得來的,但是其實我們也可以大概通過計算機的主頻來估算過來。
計算機的 主頻 表示的是每秒鐘產生出來的脈沖個數。我的 MacBook Air CPU 主頻是 1.7G 的,所以它的 CPU 每秒產生了 17 億次脈沖。每次脈沖 CPU 可以執行一條基本的匯編指令。而我們在做 ACM 競賽時,代碼長度通常在 100 行左右,一個循環里面的代碼差不多是 100 - 200 條匯編指令,所以 1000 萬次循環差不多需要 10 億 - 20 億次脈沖來執行匯編指令。當然,這只是一個估算,每一個循環指行的時間和這個循環里面執行的代碼邏輯密切相關,所以這個辦法只是大概估計,不可嚴格依賴。
有人問,會產生這么多匯編代碼嗎?不信的話,其實你完全可以用 Xcode 試試,試出來的結果只會多不會少。在 Xcode 下用 cmd + opt + enter 選擇代碼分欄模式,然后在右邊編輯器上選擇「Assembly」, 就可以方便地看到左邊源碼對應的匯編代碼,如下所示:
總結
總結一下學習時間復雜度的知識對于我們的工作有什么用:
對于不同的數據規模,能夠決策采用不同的解決方案。
了解什么情況下用暴力解法就能夠解決問題,避免寫復雜的代碼。
在寫代碼之前,就能夠預估程序的運行時間,從而可以知道是否能夠滿足產品需求。
在程序出現性能瓶頸時,能夠有解決方案而不是抓瞎。
當然,對于大部分人,在 99% 的工作時間內,我們只是做做 iOS 的 UI 界面、處理一些業務邏輯、發一些網絡請求、存一些數據到 SQLite 中。或許一年之中,用得上這些知識的只有一、兩天時間。
但是,這某種程度上就決定了一個程序員的層次和水平,你覺得呢?
?
?
? ?通常,對于一個給定的算法,我們要做 兩項分析。第一是從數學上證明算法的正確性,這一步主要用到形式化證明的方法及相關推理模式,如循環不變式、數學歸納法等。而在證明算法是正確的基礎上,第二部就是分析算法的時間復雜度。算法的時間復雜度反映了程序執行時間隨輸入規模增長而增長的量級,在很大程度上能很好反映出算法的優劣與否。因此,作為程序員,掌握基本的算法時間復雜度分析方法是很有必要的。
?????? 算法執行時間需通過依據該算法編制的程序在計算機上運行時所消耗的時間來度量。而度量一個程序的執行時間通常有兩種方法。
一、事后統計的方法
????????這種方法可行,但不是一個好的方法。該方法有兩個缺陷:一是要想對設計的算法的運行性能進行評測,必須先依據算法編制相應的程序并實際運行;二是所得時間的統計量依賴于計算機的硬件、軟件等環境因素,有時容易掩蓋算法本身的優勢。
二、事前分析估算的方法
??????? 因事后統計方法更多的依賴于計算機的硬件、軟件等環境因素,有時容易掩蓋算法本身的優劣。因此人們常常采用事前分析估算的方法。
在編寫程序前,依據統計方法對算法進行估算。一個用高級語言編寫的程序在計算機上運行時所消耗的時間取決于下列因素:
??????(1).?算法采用的策略、方法;(2).?編譯產生的代碼質量;(3).?問題的輸入規模;(4).??機器執行指令的速度。
?????一個算法是由控制結構(順序、分支和循環3種)和原操作(指固有數據類型的操作)構成的,則算法時間取決于兩者的綜合效果。為了便于比較同一個問題的不同算法,通常的做法是,從算法中選取一種對于所研究的問題(或算法類型)來說是基本操作的原操作,以該基本操作的重復執行的次數作為算法的時間量度。
1、時間復雜度?
(1)時間頻度?一個算法執行所耗費的時間,從理論上是不能算出來的,必須上機運行測試才能知道。但我們不可能也沒有必要對每個算法都上機測試,只需知道哪個算法花費的時間多,哪個算法花費的時間少就可以了。并且一個算法花費的時間與算法中語句的執行次數成正比例,哪個算法中語句執行次數多,它花費時間就多。一個算法中的語句執行次數稱為語句頻度或時間頻度。記為T(n)。
(2)時間復雜度?在剛才提到的時間頻度中,n稱為問題的規模,當n不斷變化時,時間頻度T(n)也會不斷變化。但有時我們想知道它變化時呈現什么規律。為此,我們引入時間復雜度概念。 一般情況下,算法中基本操作重復執行的次數是問題規模n的某個函數,用T(n)表示,若有某個輔助函數f(n),使得當n趨近于無窮大時,T(n)/f(n)的極限值為不等于零的常數,則稱f(n)是T(n)的同數量級函數。記作T(n)=O(f(n)),稱O(f(n))?為算法的漸進時間復雜度,簡稱時間復雜度。
???????另外,上面公式中用到的 Landau符號其實是由德國數論學家保羅·巴赫曼(Paul Bachmann)在其1892年的著作《解析數論》首先引入,由另一位德國數論學家艾德蒙·朗道(Edmund Landau)推廣。Landau符號的作用在于用簡單的函數來描述復雜函數行為,給出一個上或下(確)界。在計算算法復雜度時一般只用到大O符號,Landau符號體系中的小o符號、Θ符號等等比較不常用。這里的O,最初是用大寫希臘字母,但現在都用大寫英語字母O;小o符號也是用小寫英語字母o,Θ符號則維持大寫希臘字母Θ。
?????? ?T (n) = Ο(f (n))?表示存在一個常數C,使得在當n趨于正無窮時總有?T (n) ≤ C * f(n)。簡單來說,就是T(n)在n趨于正無窮時最大也就跟f(n)差不多大。也就是說當n趨于正無窮時T (n)的上界是C * f(n)。其雖然對f(n)沒有規定,但是一般都是取盡可能簡單的函數。例如,O(2n2+n +1) = O (3n2+n+3) = O (7n2?+ n) =?O (?n2?)?,一般都只用O(n2)表示就可以了。注意到大O符號里隱藏著一個常數C,所以f(n)里一般不加系數。如果把T(n)當做一棵樹,那么O(f(n))所表達的就是樹干,只關心其中的主干,其他的細枝末節全都拋棄不管。
??????? 在各種不同算法中,若算法中語句執行次數為一個常數,則時間復雜度為O(1),另外,在時間頻度不相同時,時間復雜度有可能相同,如T(n)=n2+3n+4與T(n)=4n2+2n+1它們的頻度不同,但時間復雜度相同,都為O(n2)。 按數量級遞增排列,常見的時間復雜度有:常數階O(1),對數階O(log2n),線性階O(n),?線性對數階O(nlog2n),平方階O(n2),立方階O(n3),..., k次方階O(nk),指數階O(2n)。隨著問題規模n的不斷增大,上述時間復雜度不斷增大,算法的執行效率越低。
???從圖中可見,我們應該盡可能選用多項式階O(nk)的算法,而不希望用指數階的算法。
????? 常見的算法時間復雜度由小到大依次為:Ο(1)<Ο(log2n)<Ο(n)<Ο(nlog2n)<Ο(n2)<Ο(n3)<…<Ο(2n)<Ο(n!)
?????? 一般情況下,對一個問題(或一類算法)只需選擇一種基本操作來討論算法的時間復雜度即可,有時也需要同時考慮幾種基本操作,甚至可以對不同的操作賦予不同的權值,以反映執行不同操作所需的相對時間,這種做法便于綜合比較解決同一問題的兩種完全不同的算法。
(3)求解算法的時間復雜度的具體步驟是:
⑴ 找出算法中的基本語句;
算法中執行次數最多的那條語句就是基本語句,通常是最內層循環的循環體。
⑵ 計算基本語句的執行次數的數量級;
只需計算基本語句執行次數的數量級,這就意味著只要保證基本語句執行次數的函數中的最高次冪正確即可,可以忽略所有低次冪和最高次冪的系數。這樣能夠簡化算法分析,并且使注意力集中在最重要的一點上:增長率。
⑶ 用大Ο記號表示算法的時間性能。
將基本語句執行次數的數量級放入大Ο記號中。
如果算法中包含嵌套的循環,則基本語句通常是最內層的循環體,如果算法中包含并列的循環,則將并列循環的時間復雜度相加。例如:
[java]?view plaincopy第一個for循環的時間復雜度為Ο(n),第二個for循環的時間復雜度為Ο(n2),則整個算法的時間復雜度為Ο(n+n2)=Ο(n2)。
Ο(1)表示基本語句的執行次數是一個常數,一般來說,只要算法中不存在循環語句,其時間復雜度就是Ο(1)。其中Ο(log2n)、Ο(n)、 Ο(nlog2n)、Ο(n2)和Ο(n3)稱為多項式時間,而Ο(2n)和Ο(n!)稱為指數時間。計算機科學家普遍認為前者(即多項式時間復雜度的算法)是有效算法,把這類問題稱為P(Polynomial,多項式)類問題,而把后者(即指數時間復雜度的算法)稱為NP(Non-Deterministic Polynomial, 非確定多項式)問題。
??????? 一般來說多項式級的復雜度是可以接受的,很多問題都有多項式級的解——也就是說,這樣的問題,對于一個規模是n的輸入,在n^k的時間內得到結果,稱為P問題。有些問題要復雜些,沒有多項式時間的解,但是可以在多項式時間里驗證某個猜測是不是正確。比如問4294967297是不是質數?如果要直接入手的話,那么要把小于4294967297的平方根的所有素數都拿出來,看看能不能整除。還好歐拉告訴我們,這個數等于641和6700417的乘積,不是素數,很好驗證的,順便麻煩轉告費馬他的猜想不成立。大數分解、Hamilton回路之類的問題,都是可以多項式時間內驗證一個“解”是否正確,這類問題叫做NP問題。
(4)在計算算法時間復雜度時有以下幾個簡單的程序分析法則:
(1).對于一些簡單的輸入輸出語句或賦值語句,近似認為需要O(1)時間
(2).對于順序結構,需要依次執行一系列語句所用的時間可采用大O下"求和法則"
求和法則:是指若算法的2個部分時間復雜度分別為 T1(n)=O(f(n))和 T2(n)=O(g(n)),則 T1(n)+T2(n)=O(max(f(n), g(n)))
特別地,若T1(m)=O(f(m)), T2(n)=O(g(n)),則 T1(m)+T2(n)=O(f(m) + g(n))
(3).對于選擇結構,如if語句,它的主要時間耗費是在執行then字句或else字句所用的時間,需注意的是檢驗條件也需要O(1)時間
(4).對于循環結構,循環語句的運行時間主要體現在多次迭代中執行循環體以及檢驗循環條件的時間耗費,一般可用大O下"乘法法則"
乘法法則: 是指若算法的2個部分時間復雜度分別為 T1(n)=O(f(n))和 T2(n)=O(g(n)),則 T1*T2=O(f(n)*g(n))
(5).對于復雜的算法,可以將它分成幾個容易估算的部分,然后利用求和法則和乘法法則技術整個算法的時間復雜度
另外還有以下2個運算法則:(1) 若g(n)=O(f(n)),則O(f(n))+ O(g(n))= O(f(n));(2) O(Cf(n)) = O(f(n)),其中C是一個正常數
?(5)下面分別對幾個常見的時間復雜度進行示例說明:
(1)、O(1)
??????? Temp=i; i=j; j=temp;?????????????????????
以上三條單個語句的頻度均為1,該程序段的執行時間是一個與問題規模n無關的常數。算法的時間復雜度為常數階,記作T(n)=O(1)。注意:如果算法的執行時間不隨著問題規模n的增加而增長,即使算法中有上千條語句,其執行時間也不過是一個較大的常數。此類算法的時間復雜度是O(1)。
(2)、O(n2)
2.1. 交換i和j的內容
[java]?view plaincopy解:因為Θ(2n2+n+1)=n2(Θ即:去低階項,去掉常數項,去掉高階項的常參得到),所以T(n)= =O(n2);
2.2.???
[java]?view plaincopy解: 語句1的頻度是n-1
????????? 語句2的頻度是(n-1)*(2n+1)=2n2-n-1
????????? f(n)=2n2-n-1+(n-1)=2n2-2;
??????? 又Θ(2n2-2)=n2
????????? 該程序的時間復雜度T(n)=O(n2).??
一般情況下,對步進循環語句只需考慮循環體中語句的執行次數,忽略該語句中步長加1、終值判別、控制轉移等成分,當有若干個循環語句時,算法的時間復雜度是由嵌套層數最多的循環語句中最內層語句的頻度f(n)決定的。?????
(3)、O(n)??????????????????????????????????????????????????????????????
[java]?view plaincopy解: 語句1的頻度:2,????????
?????????? 語句2的頻度: n,????????
????????? 語句3的頻度: n-1,????????
????????? 語句4的頻度:n-1,????
????????? 語句5的頻度:n-1,??????????????????????????????????
????????? T(n)=2+n+3(n-1)=4n-1=O(n).
(4)、O(log2n)
解: 語句1的頻度是1,??
????????? 設語句2的頻度是f(n),?? 則:2^f(n)<=n;f(n)<=log2n????
????????? 取最大值f(n)=log2n,
????????? T(n)=O(log2n?)
(5)、O(n3)?
[java]?view plaincopy解:當i=m, j=k的時候,內層循環的次數為k當i=m時, j 可以取 0,1,...,m-1 , 所以這里最內循環共進行了0+1+...+m-1=(m-1)m/2次所以,i從0取到n, 則循環共進行了: 0+(1-1)*1/2+...+(n-1)n/2=n(n+1)(n-1)/6所以時間復雜度為O(n3).
(5)常用的算法的時間復雜度和空間復雜度
一個經驗規則:其中c是一個常量,如果一個算法的復雜度為c 、?log2n?、n 、 n*log2n?,那么這個算法時間效率比較高 ,如果是2n?,3n?,n!,那么稍微大一些的n就會令這個算法不能動了,居于中間的幾個則差強人意。
???????算法時間復雜度分析是一個很重要的問題,任何一個程序員都應該熟練掌握其概念和基本方法,而且要善于從數學層面上探尋其本質,才能準確理解其內涵。
2、算法的空間復雜度
??????? 類似于時間復雜度的討論,一個算法的空間復雜度(Space Complexity)S(n)定義為該算法所耗費的存儲空間,它也是問題規模n的函數。漸近空間復雜度也常常簡稱為空間復雜度。
空間復雜度(Space Complexity)是對一個算法在運行過程中臨時占用存儲空間大小的量度。一個算法在計算機存儲器上所占用的存儲空間,包括存儲算法本身所占用的存儲空間,算法的輸入輸出數據所占用的存儲空間和算法在運行過程中臨時占用的存儲空間這三個方面。算法的輸入輸出數據所占用的存儲空間是由要解決的問題決定的,是通過參數表由調用函數傳遞而來的,它不隨本算法的不同而改變。存儲算法本身所占用的存儲空間與算法書寫的長短成正比,要壓縮這方面的存儲空間,就必須編寫出較短的算法。算法在運行過程中臨時占用的存儲空間隨算法的不同而異,有的算法只需要占用少量的臨時工作單元,而且不隨問題規模的大小而改變,我們稱這種算法是“就地\"進行的,是節省存儲的算法,如這一節介紹過的幾個算法都是如此;有的算法需要占用的臨時工作單元數與解決問題的規模n有關,它隨著n的增大而增大,當n較大時,將占用較多的存儲單元,例如將在第九章介紹的快速排序和歸并排序算法就屬于這種情況。
如當一個算法的空間復雜度為一個常量,即不隨被處理數據量n的大小而改變時,可表示為O(1);當一個算法的空間復雜度與以2為底的n的對數成正比時,可表示為0(10g2n);當一個算法的空I司復雜度與n成線性比例關系時,可表示為0(n).若形參為數組,則只需要為它分配一個存儲由實參傳送來的一個地址指針的空間,即一個機器字長空間;若形參為引用方式,則也只需要為其分配存儲一個地址的空間,用它來存儲對應實參變量的地址,以便由系統自動引用實參變量。
參考1:http://www.cnblogs.com/songQQ/archive/2009/10/20/1587122.html
參考2?:http://www.cppblog.com/85940806/archive/2011/03/12/141672.html
頂總結
以上是生活随笔為你收集整理的时间复杂度和空间复杂度的故事的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 在zabbix web上进行监控主机配置
- 下一篇: Java从网络批量读取图片并保存至本网站