圖資料儲存結構詳解
阿新 • • 發佈:2019-01-22
邊編號 | 起始節點編號 | 終止節點編號 | 權重 |
---|---|---|---|
1 | 1 | 3 | 5 |
2 | 1 | 5 | 4 |
3 | 1 | 6 | 2 |
4 | 2 | 3 | 1 |
5 | 2 | 5 | 6 |
6 | 3 | 1 | 5 |
7 | 3 | 2 | 1 |
8 | 3 | 4 | 3 |
9 | 4 | 3 | 3 |
10 | 4 | 6 | 5 |
11 | 5 | 1 | 4 |
12 | 5 | 2 | 6 |
13 | 6 | 1 | 2 |
14 | 6 | 4 | 5 |
2)關係資料庫+文字
此種方法就是將節點的詳細資訊儲存到資料庫中,所以還使用上面的節點關係表,而此處的邊就不能儲存在資料庫中了,而是儲存在文字中,此處就不對節點儲存進行詳細的介紹了。上面最後說過一個節點和其鄰接節點就會構成一條邊,所以此處就是通過儲存鄰接節點來對邊進行儲存了。我們是將每個節點的鄰接節點通過陣列寫到文字中,可知一個節點的鄰接節點不止一個,所以每個節點的鄰接節點是儲存在文字中的某一塊區域,所以此處需要引入偏移量的概念,此處每個節點對應了一個偏移量,這個偏移量是做什麼用的呢?就是指出這個節點的鄰接節點資訊是儲存在文字的那個位置開始。同時可以知道一個節點的鄰接節點個數是和該節點的度有關的,例如上面的1節點有3個度,那麼1將有3個鄰接節點,所以將產生3條邊,這是一個重要的概念,因為度的大小和一個節點的鄰接節點個數相同,同時也影響該節點在儲存鄰接節點文字所佔據的大小。說了這麼多肯定會暈的,下面還是舉個例子說明吧:位置 | 鄰接節點 |
---|---|
0 | 3 |
1 | 5 |
2 | 6 |
3 | 3 |
4 | 5 |
5 | 1 |
6 | 2 |
7 | 4 |
8 | 3 |
9 | 6 |
10 | 1 |
11 | 2 |
12 | 1 |
13 | 4 |
節點編號 | 度 |
---|---|
1 | 3 |
2 | 2 |
3 | 3 |
4 | 2 |
5 | 2 |
6 | 2 |
節點編號 | 偏移量 |
---|---|
1 | 0 |
2 | 3 |
3 | 5 |
4 | 8 |
5 | 10 |
6 | 12 |
此處可以看出,1的鄰接節點是儲存在鄰接節點文字的0位置到2的位置,2的鄰接節點是儲存在3位置到4的位置.....其他的節點也可以以此退出,其實在文字中儲存是以陣列儲存的,並沒有上面那樣的結構,如鄰接節點文字:[3,5,6,3,5,1,2,4,3,6,1,2,1,4],在文字中每個數字一行,而偏移量就是某個節點的鄰接節點儲存位置的起始位置,而長度為該節點的度的大小,同樣節點的度和偏移量也是這樣儲存的,也是每個陣列一行,同時行數和節點的編號要對應,如1節點是第一行,2節點是第二行....因為這些值是和節點一一對應的。在我們的程式中其實是將這些資訊通過IO讀到陣列中,如我們定義一個adjancent[]陣列用於存放鄰接節點的,adjancentoffset[]儲存偏移量的,degree[]是儲存節點度的。如1節點的度是degree[0],它的鄰接節點偏移量是為:adjancentoffset[0],那麼1節點的鄰接節點是儲存在adjancent[adjancentoffset[0]]到adjancent[adjancentoffset[0]+degree[0]-1]中,那麼就會產生相應的邊,那麼邊的編號就是adjancentoffset[0]~adjancentoffset[0]+degree[0]-1,可以看到邊的編號和鄰接節點的儲存位置是對應的,因為一個鄰接節點對應了一條邊,上面已經講過,此處就不在贅述。我們就可以將這些陣列存放在程式中,並利用這些陣列還原圖結構,例如:我們還是以1節點開始擴充套件圖:1的鄰接節點有3、5和6,此時就擴充套件了三個節點,在通過這三個節點擴充套件它們各自的鄰接節點,依此類推,邊還原了圖的結構,該種方法,避免了大量的資料庫的訪問,而是通過把圖儲存在文字中,並一次性的讀入到記憶體中,並通過迭代還原圖結構。但這種操作容易產生幾種缺陷,第一、圖的資訊更新不方便,應為向圖中添加了一些節點,那麼就要重新生成這些文字,第二、這些圖的資訊全部儲存在記憶體中,使得圖的大小收到記憶體的限制。我做試驗的時候,儲存2百萬個節點2百多萬條邊的圖佔記憶體20多M。所以多餘圖的節點個數不怎麼更改,圖的節點個數不不億量級的可以採取這樣的方式儲存。關於該種方法的使用詳細見