1. 程式人生 > >演算法的空間複雜度(空間代價)

演算法的空間複雜度(空間代價)

空間代價

  • 時間代價是相對於處理某個資料結構的演算法而言的,而空間代價是相對於資料結構本身而言的。

    例1:一個包含n個整數的一維陣列空間代價為多少?
    如果每個整數佔用c位元組,則整個陣列需要cn位元組的空間,即O(n).

    例2:假設要記錄n個人互相之間的朋友關係,就可以用一個n*n的陣列來實現。陣列的每一行表示某人的所有朋友,每一列則顯示誰是朋友。
    對於n個人來說,陣列總規模為O(n^2).

  • 一個數據結構的主要目的是用恰當的方法儲存資料,使我們能夠簡單而有效地對其進行訪問。為此,必須在這個資料結構中加上一些附加資訊,指明資料存放在何處(例如,連結串列的每個元素都帶有一個指標,指向表中的下一個元素)。所有這類並非真正資料的附加資訊稱為結構性開銷(overhead)

    理論上,這種結構性開銷應該儘量小,而訪問路徑又應該儘可能多且有效。這種相互矛盾的目標之間的權衡正是研究資料結構的樂趣和魅力所在。

  • 演算法設計有一個重要原則,即空間/時間權衡原則(space/time tradeoff)

    例3:查詢表(lookup table)中預先存放了一些函式值,從而不必每次呼叫時都重新計算。
    例如階乘函式,如果使用32位的int型變數來儲存,則12!是允許範圍內的最大函式值。如果一個程式中需要多次重複計算階乘,那麼把這12個函式值預先存放在一個查詢表中將會大大減少執行時間。程式需要n!(n<12)的值時,只要簡單查一下查詢表就行了。與每次計算階乘的時間代價相比,犧牲一點點空間來存放查詢表很值得。
    查詢表的另一個用途是存放某些具有較大開銷的函式的近似值,如sin,cos等。

  • 程式空間、時間代價相互關係的另一個原則是對處理儲存在磁碟上的資訊(外存資訊)而言的。有意思的是,基於磁碟的空間/時間權衡原則(disk-based space/time tradeoff)與上面所說的空間/時間權衡原則幾乎是完全相反的。基於磁碟的空間/時間權衡原則為:在磁碟上的儲存代價越小,程式執行得越快

    這是因為從磁碟上讀取資料的時間代價遠遠大於用於計算的時間代價,於是幾乎所有用於對資料進行解壓縮的額外操作的時間代價,都小於減少儲存代價後節約下來的讀盤時間。

  • 一個程式的空間複雜度是指執行完一個程式所需記憶體的大小。利用程式的空間複雜度,可以對程式的執行所需要的記憶體多少有個預先估計。一個程式執行時除了需要儲存空間和儲存本身所使用的指令、常數、變數和輸入資料外,還需要一些對資料進行操作的工作單元和儲存一些為現實計算所需資訊的輔助空間。程式執行時所需儲存空間包括以下兩部分。 
    (1)固定部分。這部分空間的大小與輸入/輸出的資料的個數多少、數值無關。主要包括指令空間(即程式碼空間)、資料空間(常量、簡單變數)等所佔的空間。這部分屬於靜態空間


    (2)可變空間,這部分空間的主要包括動態分配的空間,以及遞迴棧所需的空間等。這部分的空間大小與演算法有關。
    一個演算法所需的儲存空間用f(n)表示。S(n)=O(f(n)),其中n為問題的規模,S(n)表示空間複雜度。

參考資料

[1]《資料結構與演算法分析(C++版)》(第二版). [美] Clifford A. Shaffer著.
[2]《時間複雜度和空間複雜度詳解》