《程式設計珠璣》程式碼之路15:節省空間的常見姿勢

心理學演算法工程師發表於2018-12-04

1:地理資訊庫中儲存鄰居的系統

地理資訊庫中的鄰居用一個點(x, y)表示,x和y在[0,199]取值,假設一共有兩千個,那麼可以用一個200*200的二位格子矩陣表示,還可以作成圖形介面,使用者點選那個格子,系統把點選訊號轉化成對應的x和y,就可以直接訪問相應鄰居,如下圖所示,格子為空表示空值,否則為相應資料。

法一:我們可以直接用一個二維陣列實現,這樣訪問起來也非常方便,但問題中也就只有2000個鄰居,而200*200=40000,也就是說只有5%左右的儲存空間可以得到利用,從空間上來說,浪費非常大。

法二:可以用下圖所示的資料結構來實現:

 

最左邊的colhead陣列,下標對應法一二維陣列中的列號,每個元素都是一個連結串列的頭指標。每個連結串列節點有兩個成員,分別是對應的行號和資料。這樣可以在常數時間找到對應的列,線上性時間找到對應的行號,然後取出需要的資料。通常來說,這個空間效能已經很不錯的,但還沒有優化到極致。

算一下哈:除了一個連結串列頭陣列,每個元素還需要一個指標和一個儲存行號的空間,最重要的是,結構體在分配空間的時候還會因為對齊等問題造成空間浪費。

法三:開闢三個陣列解決問題,第一個firstincol陣列,下標對應列號,下標對應的數值代表這一列元素在陣列row的第一個位置。陣列row代表對應元素的行號。例如firstincol[0]值為0,代表第0列第一個元素在row[0],對應的pointnum[0]就是相應的數值,不難發現,根據firstincol[0 + 1]就可以找到firstincol[0]最後一個元素的位置。

如此一來,一個鄰居只需要兩個int來解決問題,而且不會因為結構體動態分配問題浪費更多空間。

當然,因為下標都在200以內,所以int其實可以替換為char,進一步節省空間。

相關文章