圖數據存儲結構詳解

圖數據存儲初見

最終版權:JDream314 如有轉載請貼出出處
       在《圖數據挖掘——基本概念》一文中詳細的講了圖數據的基本概念,並在圖數據挖掘之圖信息獲取及存儲》一文中描述了圖的信息獲取,但並沒有對圖數據的存儲進行詳細的介紹,該篇將就圖數據存儲給大家介紹一下,如有不對之處希望多多指出!
        我們都知道圖數據主要的信息是節點、邊和權重,如何存儲這些信息是至關重要的,同時採用何種存儲結構對圖的還原影響非常大。今天將介紹兩種圖的存儲方式:1)關係數據庫存儲 2)關係數據庫+文本。

        1)關係數據庫存儲

         如上面的圖,我們知道其中有V1、V2、V3、 V4、 V5、 V6節點,同時也有7條邊,並對應了各自的權重。如何使用關係數據庫來存儲這些信息,將在此處給大家介紹。要存儲這些信息需要創建一個關係表,第一個就是節點表:用於存儲節點的詳細信息(節點裏麪包含的數據),並給節點一個唯一的編號,如1、2、3、4......。另外還要創建一個邊關係表:用於存儲邊的詳細信息,我們知道邊一般包含兩個節點和權重,我們此處稱兩個節點爲起始節點和終止節點。如何將這些信息存儲到數據庫中,下面將舉例說明:
節點關係表
節點編號 節點信息
1 V1
2 V2
3 V3
4 V4
5 V5
6 V6
邊關係表
邊編號 起始節點編號 終止節點編號 權重
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
         由於上面給出的圖是無向圖,所以兩個節點之間的邊的關係是相互的,如V1——>V3那麼V3——>V1。所以邊的關係表中有14條記錄。上面列舉出了節點的存儲結構和邊的存儲結構,那麼如何根據這些信息還原圖的結構呢?其實要還原圖,只需關注邊的關係表就夠了,而節點關係表只是存儲節點詳細信息的,而圖的搜索和數據挖掘在開始時是不需要這些節點的詳細信息,而是在挖掘到了有用的信息時才從關係表中獲取每個節點的詳細信息。所以在進行搜索或者其他的圖挖掘的時候完全不需要知道節點詳細信息,而是隻要拿到每個節點的唯一編號就行了,當需要時再根據這個編號到節點關係表中獲取節點的信息,這樣做可以減少圖所佔用的內存,因爲此時每個節點只是一個數字,而不是那些複雜的信息。廢話不多說,那麼如何根據邊關係表得到圖呢?還原圖其實只需選擇一個節點出發,對圖進行探索就行了。如此處選擇編號爲1的節點(此後將以節點編號表示一個節點)對圖進行探索:可以根據上面的表知道和1相連的節點有3、5和6,那麼就存在1——>3,1——>5和1——>6(此時是找以1爲起始節點的邊),可以知道現在圖的結構已經探索到了3、5和6節點,那麼接下來將對3、5和6進行探索,即獲取以3爲起始節點、5爲起始節點和6爲起始節點的邊,依次類推,將構造出一個圖的結構。大家可能都看得到,其實上面的3、5和6都是1的鄰接節點,所以可以推出:一個鄰接節點將產生一條邊(此處的鄰接節點是和節點直接相連的節點,並且可達,如是有向邊,這就要考慮方向性,反向是不可達的,所以此時不存在相互性),所以圖的邊可以直接更具節點的鄰接節點來進行存儲,這樣可以簡化圖的還原。大家可能發現這樣通過數據庫來對圖進行擴展是非常漫長的,如果圖有上百萬個節點,那麼下個要通過這樣的數據庫來進行還原圖那是非常艱苦的。下面介紹一種相對比較好的存儲方式。

      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。所以多餘圖的節點個數不怎麼更改,圖的節點個數不不億量級的可以採取這樣的方式存儲。關於該種方法的使用詳細見《一種圖存儲結構【看了之後你會對圖的結構有新的認識》
       此文到此已差不多結束,希望如有什麼不對的地方洗完指出!歡迎評論該文!
       謝謝瀏覽!此文完!
發佈了40 篇原創文章 · 獲贊 26 · 訪問量 41萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章