當前位置:首頁 » 存儲配置 » 圖的有向存儲

圖的有向存儲

發布時間: 2022-09-26 18:06:38

❶ 數據結構——圖

轉自: http://www.cnblogs.com/mcgrady/archive/2013/09/23/3335847.html

閱讀目錄

一,圖的定義

二,圖相關的概念和術語

三,圖的創建和遍歷

四,最小生成樹和最短路徑

五,演算法實現

這一篇我們要總結的是圖(Graph),圖可能比我們之前學習的線性結構和樹形結構都要復雜,不過沒有關系,我們一點一點地來總結,那麼關於圖我想從以下幾點進行總結:

1,圖的定義?

2,圖相關的概念和術語?

3,圖的創建和遍歷?

4,最小生成樹和最短路徑?

5,演算法實現?

一,圖的定義

什麼是圖呢?

圖是一種復雜的非線性結構。

在線性結構中,數據元素之間滿足唯一的線性關系,每個數據元素(除第一個和最後一個外)只有一個直接前趨和一個直接後繼;

在樹形結構中,數據元素之間有著明顯的層次關系,並且每個數據元素只與上一層中的一個元素(雙親節點)及下一層的多個元素(孩子節點)相關;

而在圖形結構中,節點之間的關系是任意的,圖中任意兩個數據元素之間都有可能相關。

圖G由兩個集合V(頂點Vertex)和E(邊Edge)組成,定義為G=(V,E)

二,圖相關的概念和術語

1,無向圖和有向圖

對於一個圖,若每條邊都是沒有方向的,則稱該圖為無向圖。圖示如下:

因此,(Vi,Vj)和(Vj,Vi)表示的是同一條邊。注意,無向圖是用小括弧,而下面介紹的有向圖是用尖括弧。

無向圖的頂點集和邊集分別表示為:

V(G)={V1,V2,V3,V4,V5}

E(G)={(V1,V2),(V1,V4),(V2,V3),(V2,V5),(V3,V4),(V3,V5),(V4,V5)}

對於一個圖G,若每條邊都是有方向的,則稱該圖為有向圖。圖示如下。

因此,和是兩條不同的有向邊。注意,有向邊又稱為弧。

有向圖的頂點集和邊集分別表示為:

V(G)={V1,V2,V3}

E(G)={,,,}

2,無向完全圖和有向完全圖

我們將具有n(n-1)/2條邊的無向圖稱為無向完全圖。同理,將具有n(n-1)條邊的有向圖稱為有向完全圖。

3,頂點的度

對於無向圖,頂點的度表示以該頂點作為一個端點的邊的數目。比如,圖(a)無向圖中頂點V3的度D(V3)=3

對於有向圖,頂點的度分為入度和出度。入度表示以該頂點為終點的入邊數目,出度是以該頂點為起點的出邊數目,該頂點的度等於其入度和出度之和。比如,頂點V1的入度ID(V1)=1,出度OD(V1)=2,所以D(V1)=ID(V1)+OD(V1)=1+2=3

記住,不管是無向圖還是有向圖,頂點數n,邊數e和頂點的度數有如下關系:

因此,就拿有向圖(b)來舉例,由公式可以得到圖G的邊數e=(D(V1)+D(V2)+D(V3))/2=(3+2+3)/2=4

4,子圖

故名思義,這個就不解釋了。

5,路徑,路徑長度和迴路

路徑,比如在無向圖G中,存在一個頂點序列Vp,Vi1,Vi2,Vi3…,Vim,Vq,使得(Vp,Vi1),(Vi1,Vi2),…,(Vim,Vq)均屬於邊集E(G),則稱頂點Vp到Vq存在一條路徑。

路徑長度,是指一條路徑上經過的邊的數量。

迴路,指一條路徑的起點和終點為同一個頂點。

6,連通圖(無向圖)

連通圖是指圖G中任意兩個頂點Vi和Vj都連通,則稱為連通圖。比如圖(b)就是連通圖。下面是一個非連通圖的例子。

上圖中,因為V5和V6是單獨的,所以是非連通圖。

7,強連通圖(有向圖)

強連通圖是對於有向圖而言的,與無向圖的連通圖類似。

8,網

帶」權值」的連通圖稱為網。如圖所示。

三,圖的創建和遍歷

1,圖的兩種存儲結構

1) 鄰接矩陣,原理就是用兩個數組,一個數組保存頂點集,一個數組保存邊集。下面的演算法實現里邊我們也是採用這種存儲結構。如下圖所示:

2) 鄰接表,鄰接表是圖的一種鏈式存儲結構。這種存儲結構類似於樹的孩子鏈表。對於圖G中每個頂點Vi,把所有鄰接於Vi的頂點Vj鏈成一個單鏈表,這個單鏈表稱為頂點Vi的鄰接表。

2,圖的兩種遍歷方法

1) 深度優先搜索遍歷

深度優先搜索DFS遍歷類似於樹的前序遍歷。其基本思路是:

a) 假設初始狀態是圖中所有頂點都未曾訪問過,則可從圖G中任意一頂點v為初始出發點,首先訪問出發點v,並將其標記為已訪問過。

b) 然後依次從v出發搜索v的每個鄰接點w,若w未曾訪問過,則以w作為新的出發點出發,繼續進行深度優先遍歷,直到圖中所有和v有路徑相通的頂點都被訪問到。

c) 若此時圖中仍有頂點未被訪問,則另選一個未曾訪問的頂點作為起點,重復上述步驟,直到圖中所有頂點都被訪問到為止。

圖示如下:

註:紅色數字代表遍歷的先後順序,所以圖(e)無向圖的深度優先遍歷的頂點訪問序列為:V0,V1,V2,V5,V4,V6,V3,V7,V8

如果採用鄰接矩陣存儲,則時間復雜度為O(n2);當採用鄰接表時時間復雜度為O(n+e)。

2) 廣度優先搜索遍歷

廣度優先搜索遍歷BFS類似於樹的按層次遍歷。其基本思路是:

a) 首先訪問出發點Vi

b) 接著依次訪問Vi的所有未被訪問過的鄰接點Vi1,Vi2,Vi3,…,Vit並均標記為已訪問過。

c) 然後再按照Vi1,Vi2,… ,Vit的次序,訪問每一個頂點的所有未曾訪問過的頂點並均標記為已訪問過,依此類推,直到圖中所有和初始出發點Vi有路徑相通的頂點都被訪問過為止。

圖示如下:

因此,圖(f)採用廣義優先搜索遍歷以V0為出發點的頂點序列為:V0,V1,V3,V4,V2,V6,V8,V5,V7

如果採用鄰接矩陣存儲,則時間復雜度為O(n2),若採用鄰接表,則時間復雜度為O(n+e)。

四,最小生成樹和最短路徑

1,最小生成樹

什麼是最小生成樹呢?在弄清什麼是最小生成樹之前,我們需要弄清什麼是生成樹?

用一句語簡單概括生成樹就是:生成樹是將圖中所有頂點以最少的邊連通的子圖。

比如圖(g)可以同時得到兩個生成樹圖(h)和圖(i)

知道了什麼是生成樹之後,我們就很容易理解什麼是最小生成樹了。所謂最小生成樹,用一句話總結就是:權值和最小的生成樹就是最小生成樹。

比如上圖中的兩個生成樹,生成樹1和生成樹2,生成樹1的權值和為:12,生成樹2的權值為:14,我們可以證明圖(h)生成樹1就是圖(g)的最小生成樹。

那麼如何構造最小生成樹呢?可以使用普里姆演算法。

2,最短路徑

求最短路徑也就是求最短路徑長度。下面是一個帶權值的有向圖,表格中分別列出了頂點V1其它各頂點的最短路徑長度。

表:頂點V1到其它各頂點的最短路徑表

從圖中可以看出,頂點V1到V4的路徑有3條(V1,V2,V4),(V1,V4),(V1,V3,V2,V4),其路徑長度分別為15,20和10,因此,V1到V4的最短路徑為(V1,V3,V2,V4)。

那麼如何求帶權有向圖的最短路徑長度呢?可以使用迪傑斯特拉(Dijkstra)演算法。

資料庫中如何存儲有向圖

方法一:用鄰接表的方法存儲,
先開辟一塊大小為n的存儲空間,每一塊存儲空間為一個鏈表的開頭,一次將數據增加到相應的鏈表裡。
方法二:用鄰接矩陣的方法存儲,
開辟一個矩陣,在相接的兩個點對應的序號的位置存儲為1,其餘為0,例如:矩陣a[100][100],1和2相連,則a[1][2]=0

❸ 有向圖的鄰接表存儲如圖所示,請畫出其鄰接矩陣存儲結構

有向圖的鄰接表存儲如圖所示,其鄰接矩陣存儲如圖:

❹ 數據結構中的圖 無向和有向,怎樣存入文件

通常圖都分為結點和弧,您存儲圖到文件可以按照這種方法來實現。
typedef struct {
int type; //標識是有向圖還是無向圖,例如0表示有向圖,非0表示無向圖
int vexnum;
char *arclist; //arclist指向一個vexnum*vexnum的矩陣,存儲節點間的弧
}CHART;

1. 寫文件時將上面的結構寫入文件,然後將vexnum*vexnum的弧矩陣寫入文件
2. 讀文件時先讀取上面的結構,然後依據vexnum先申請一個vexnum*vexnum大小的空間
賦值給arclist,然後從文件繼續讀取vexnum*vexnum大小的數據存儲到arclist指向的數
組中。

❺ 圖的存儲結構——所存儲的信息有哪些

一、鄰接矩陣存儲方法

鄰接矩陣是表示頂點之間相鄰關系的矩陣。

設G=(V,E)是具有n(n>0)個頂點的圖,頂點的順序依次為0~n-1,則G的鄰接矩陣A是n階方陣,其定義如下:

(1)如果G是無向圖,則:

A[i][j]=1:若(i,j)∈E(G) 0:其他

(2)如果G是有向圖,則:

A[i][j]=1:若<i,j>∈E(G) 0:其他

(3)如果G是帶權無向圖,則:

A[i][j]= wij :若i≠j且(i,j)∈E(G) 0:i=j ∞:其他

(4)如果G是帶權有向圖,則:

A[i][j]= wij :若i≠j且<i,j>∈E(G) 0:i=j∞:其他

注意:帶權圖和不帶權圖表示的元素類型不同。


帶權圖(不論有向還是無向圖)A[i][j]用double表示,不帶權圖(不論有向還是無向圖)A[i][j]用int表示。

用一維數組G[ ]存儲有4個頂點的無向圖如:G[ ] = { 0, 1, 0, 1, 1, 0, 0, 0, 1, 0 }

則頂點2和頂點0之間是有邊的。

如:

鄰接矩陣的特點如下:

(1)圖的鄰接矩陣表示是唯一的。

(2)無向圖的鄰接矩陣一定是一個對稱矩陣。因此,按照壓縮存儲的思想,在具體存放鄰接矩陣時只需存放上(或下)三角形陣的元素即可。

(3)不帶權的有向圖的鄰接矩陣一般來說是一個稀疏矩陣。因此,當圖的頂點較多時,可以採用三元組表的方法存儲鄰接矩陣。

(4)對於無向圖,鄰接矩陣的第i行(或第i列)非零元素(或非∞元素)的個數正好是第i個頂點的度。

(5)對於有向圖,鄰接矩陣的第i行(或第i列)非零元素(或非∞元素)的個數正好是第i個頂點的出度(或入度)。

(6)用鄰接矩陣方法存儲圖,很容易確定圖中任意兩個頂點之間是否有邊相連。但是,要確定圖中有多少條邊,則必須按行、按列對每個元素進行檢測,所花費的時間代價很大。這是用鄰接矩陣存儲圖的局限性。

鄰接矩陣的數據類型定義如下:

#define MAXV <最大頂點個數>

typedef struct

{ int no; //頂點編號

InfoType info; //頂點其他信息

} VertexType; //頂點類型

typedef struct //圖的定義

{ int edges[MAXV][MAXV]; //鄰接矩陣

int n,e; //頂點數,弧數

VertexType vexs[MAXV]; //存放頂點信息

} MGraph; //圖的鄰接矩陣表示類型


二、 鄰接表存儲方法

圖的鄰接表存儲方法是一種順序分配與鏈式分配相結合的存儲方法。

在鄰接表中,對圖中每個頂點建立一個單鏈表,第i個單鏈表中的節點表示依附於頂點i的邊(對有向圖是以頂點i為尾的邊)。每個單鏈表上附設一個表頭節點。

其中,表節點由三個域組成,adjvex指示與頂點i鄰接的點在圖中的位置,nextarc指示下一條邊或弧的節點,info存儲與邊或弧相關的信息,如權值等。

表頭節點由兩個域組成,data存儲頂點i的名稱或其他信息,firstarc指向鏈表中第一個節點。

typedef struct ANode

{ int adjvex; //該邊的終點編號

struct ANode *nextarc; //指向下一條邊的指針

InfoType info; //該邊的相關信息

} ArcNode; //邊表節點類型


typedef struct Vnode

{ Vertex data; //頂點信息

ArcNode *firstarc; //指向第一條邊

} VNode; //鄰接表頭節點類型

typedef VNode AdjList[MAXV]; //AdjList是鄰接表類型

typedef struct

{ AdjList adjlist; //鄰接表

int n,e; //圖中頂點數n和邊數e

} ALGraph; //完整的圖鄰接表類型


鄰接表的特點如下:

(1)鄰接表表示不唯一。這是因為在每個頂點對應的單鏈表中,各邊節點的鏈接次序可以是任意的,取決於建立鄰接表的演算法以及邊的輸入次序。

(2)對於有n個頂點和e條邊的無向圖,其鄰接表有n個頂點節點和2e個邊節點。顯然,在總的邊數小於n(n-1)/2的情況下,鄰接表比鄰接矩陣要節省空間。

(3)對於無向圖,鄰接表的頂點i對應的第i個鏈表的邊節點數目正好是頂點i的度。

(4)對於有向圖,鄰接表的頂點i對應的第i個鏈表的邊節點數目僅僅是頂點i的出度。其入度為鄰接表中所有adjvex域值為i的邊節點數目。

例, 給定一個具有n個節點的無向圖的鄰接矩陣和鄰接表。

(1)設計一個將鄰接矩陣轉換為鄰接表的演算法;

(2)設計一個將鄰接表轉換為鄰接矩陣的演算法;

(3)分析上述兩個演算法的時間復雜度。

解:

(1)在鄰接矩陣上查找值不為0的元素,找到這樣的元素後創建一個表節點並在鄰接表對應的單鏈表中採用前插法插入該節點。

void MatToList(MGraph g,ALGraph *&G)

//將鄰接矩陣g轉換成鄰接表G

{ int i,j,n=g.n; ArcNode *p; //n為頂點數

G=(ALGraph *)malloc(sizeof(ALGraph));

for (i=0;i<n;i++) //給所有頭節點的指針域置初值

G->adjlist[i].firstarc=NULL;

for (i=0;i<n;i++) //檢查鄰接矩陣中每個元素

for (j=n-1;j>=0;j--)

if (g.edges[i][j]!=0)

{ p=(ArcNode *)malloc(sizeof(ArcNode));

//創建節點*p

p->adjvex=j;

p->nextarc=G->adjlist[i].firstarc;

//將*p鏈到鏈表頭

G->adjlist[i].firstarc=p;

}

G->n=n;G->e=g.e;


}


(2)在鄰接表上查找相鄰節點,找到後修改相應鄰接矩陣元素的值。

void ListToMat(ALGraph *G,MGraph &g)

{ int i,j,n=G->n;ArcNode *p;

for (i=0;i<n;i++)

{ p=G->adjlist[i].firstarc;

while (p!=NULL)

{ g.edges[i][p->adjvex]=1;

p=p->nextarc;

}

}

g.n=n;g.e=G->e;

}


(3)演算法1的時間復雜度均為O(n2)。演算法2的時間復雜度為O(n+e),其中e為圖的邊數。

❻ 圖的五種存儲結構

圖的鄰接矩陣(Adjacency Matrix): 圖的鄰接矩陣用兩個數組來表示圖。一個一維數組存儲圖中頂點信息,另一個二維數組(一般稱之為鄰接矩陣)來存儲圖中的邊或者弧的信息。從鄰接矩陣中我們自然知道一個頂點的度(對於無向圖)或者有向圖中一個頂點的入度出度信息。

假設圖G有n個頂點,則鄰接矩陣是一個n*n的方陣。
1.對於如果圖上的每條邊不帶權值來說,那麼我們就用真(一般為1)和假(一般為0)來表示一個頂點到另一個頂點存不存在邊。下面是一個圖的鄰接矩陣的定義:

鄰接矩陣法實現帶權值的無向圖的創建如下:

按照如圖輸入各邊(不重復)

測試程序如下:

結果可得該矩陣,證明創建樹成功。 假設n個頂點e條邊的創建,createGraph演算法的時間復雜度為O(n+n*n+e)。如果需要創建一個有向圖,那麼和上面一樣一個一個錄入邊下標和權值。

鄰接矩陣這種存儲結構的優缺點: 缺點是對於邊數相對頂點較少的稀疏圖來說會存在極大的空間浪費。假設有n個頂點,優點是對於有向完全圖和無向完全圖來說鄰接矩陣是一種不錯的存儲結構,浪費的話也只浪費了n個頂點的容量。

在樹的存儲結構一節中我們提到對於孩子表示法的第三種:用一段連續的存儲單元(數組)存儲樹中的所有結點,利用一個單鏈表來存儲數組中每個結點的孩子的信息。對於圖的存儲結構來說,我們也可以利用這種方法實現圖的存儲

鄰接表(Adjacency List): 這種數組與鏈表相結合的存儲方法叫做鄰接表。1.為什麼不也用單鏈表存儲圖的結點信息呢?原因就是數組這種順序存儲結構讀取結點信息速率快。對於頂點數組中,每個數據元素還需要存儲一個指向第一個鄰接頂點的指針,這樣才可以查找邊的信息2.圖中每個頂點Vi(i > 0)的所有鄰接點構成一個線性表 (在無向圖中這個線性表稱為Vi的邊表,有向圖中稱為頂點作為弧尾的出邊表) ,由於鄰接點的不確定性,所以用鏈表存儲,有多少個鄰接點就malloc一個空間存儲鄰接點,這樣更不會造成空間的浪費(與鄰接矩陣相比來說)。3.對於鄰接表中的某個頂點來說,用戶關心的是這個頂點的鄰接點,完全可以遍歷用單鏈表設計成的邊表或者出邊表得到,所以沒必要設計成雙鏈表。

鄰接表的存儲結構:
假設現在有一無向圖G,如下圖:

從鄰接表結構中,知道一個頂點的度或者判斷兩個頂點之間是否存在邊或者求一個頂點的所有鄰接頂點是很容易的。

假設現在有一有向圖G,如下圖:

無向圖的鄰接表創建示例如下:

假設在上圖(無向圖)中的V0V1V2V3頂點值為ABCD,則依據下面測試程序可得結果:

鄰接表的優缺點: 優點是:鄰接表存儲圖,既能夠知道一個頂點的度和頂點的鄰接結點的信息,並且更不會造成空間的浪費。缺點是鄰接表存儲有向圖時,如果關心的是頂點的出度問題自然用鄰接表結構,但是想了解入度需要遍歷圖才知道(需要考慮逆鄰接表)。

十字鏈表(Orthogonal List) :有向圖的一種存儲方法,它把鄰接表和逆鄰接表結合起來,因此在十字鏈表結構中可以知道一個頂點的入度和出度情況。
重新定義頂點表的結點如下圖:

現在有一有向圖如下圖:

則它的存儲結構示意圖為:

其定義如下:

十字鏈表是用來存儲有向圖的,這樣可以看出一個頂點的出入度信息。對於無向圖來說完全沒必要用十字鏈表來存儲。

在無向圖中,因為我們關注的是頂點的信息,在考慮節約空間的情況下我們利用鄰接表來存儲無向圖。但是如果我們關注的是邊的信息,例如需要刪除某條邊對於鄰接表來說是挺繁瑣的。它需要操作兩個單鏈表刪除兩個結點。因此我們仿照十字鏈表的方式對邊表結點結構重新定義如下圖:

它的鄰接多重表結構為:

多重鄰接表的優點:對於邊的操作相比於鄰接表來說更加方便。比如說我們現在需要刪除(V0,V2)這條邊,只需將69步驟中的指針改為nullptr即可。

邊集數組(edgeset array): 邊集數組是由兩個數組組成,一個存儲頂點信息,另一個存儲邊的信息,這個邊數組中的每個數據元素由起點下標,終點下標,和權組成(如果邊上含有權值的話)。
邊數組結構如下圖:

邊集數組實現圖的存儲的優缺點:優點是對於邊的操作方便快捷,操作的只是數組元素。比如說刪除某條邊,只需要刪除一個數組元素。缺點是:對於圖的頂點信息,我們只有遍歷整個邊數組才知道,這個費時。因此對於關注邊的操作來說,邊集數組更加方便。

❼ 有向圖和無向圖的有關知識

有/無 向圖如果給圖的每條邊規定一個方向,那麼得到的圖稱為有向圖,其邊也稱為有向邊。在有向圖中,與一個節點相關聯的邊有出邊和入邊之分,而與一個有向邊關聯的兩個點也有始點和終點之分。相反,邊沒有方向的圖稱為無向圖。[編輯]簡單圖一個圖如果沒有兩條邊,它們所關聯的兩個點都相同(在有向圖中,沒有兩條邊的起點終點都分別相同);每條邊所關聯的是兩個不同的頂點則稱為簡單圖(simple graph)。簡單的有向圖和無向圖都可以使用以上的「二元組的定義」,但形如(x,x)的序對不能屬於E。而無向圖的邊集必須是對稱的,即如果 ,那麼 。[編輯]多重圖若允許兩結點間的邊數多於一條,又允許頂點通過同一條邊和自己關聯,則為多重圖的概念。它只能用「三元組的定義」。[編輯]基本術語在頂點1有一個環階(Order):圖G中頂集V的大小稱作圖G的階。子圖(Sub-Graph):圖G'稱作圖G的子圖如果以及 。生成子圖(Spanning Sub-Graph):指滿足條件V(G') =V(G)的G的子圖G。度(Degree)是一個頂點的度是指與該頂點相關聯的總邊數,頂點v的度記作d(v)。度和邊有如下關系:。出度(out-degree) 和入度 (in-degree):對有向圖而言,頂點的度還可分為出度和入度。一個頂點的出度為 do ,是指有 do 條邊以該頂點為起點,或說與該點關聯的出邊共有do條。入度的概念也類似。鄰接矩陣環(loop):若一條邊的兩個頂點相同,則此邊稱作環。路徑(path):從頂點 u 到頂點 v 的一條路徑是指一個序列v0,e1,v1,e2,v2,...ek,vk, ei的起點終點為vi及vi - 1; k 稱作路徑的長度; v_0=u,稱為路徑的起點; v_k=v,稱為路徑的終點。如果 u=v,稱該路徑是閉的,反之則稱為開的;如果 v_1 , ... , v_k 兩兩不等,則稱之為簡單路徑(simple path)(注意,u=v 是允許的)。行跡(trace):如果路徑P(u,v)中邊各不相同,則該路徑稱為u到v的一條行跡。軌道(track):即簡單路徑。閉的行跡稱作迴路(circuit),閉的軌道稱作圈(Cycle)。(現存文獻中的命名法並無統一標准。比如在另一種定義中,walk 對應上述的 path,path 對應上述的 track , trail 對應上述的 trace。)距離(distance): 從頂點 u 出發到頂點 v 的最短路徑若存在,則此路徑的長度稱作從 u 到 v 的距離。若從 u 到 v 根本不存在路徑,則記該距離為無窮(∞)。距離矩陣橋(bridge):若去掉一條邊,便會使得整個圖不連通,該邊稱為橋。[編輯]圖的存儲表示數組(鄰接矩陣)存儲表示(有向或無向)鄰接表存儲表示前向星存儲表示有向圖的十字鏈表存儲表示無向圖的鄰接多重表存儲表示一個不帶權圖中若兩點不相鄰,鄰接矩陣相應位置為0,對帶權圖(網),相應位置為∞。一個圖的鄰接矩陣表示是唯一的,但其鄰接表表示不唯一。在鄰接表中,對圖中每個頂點建立一個單鏈表(並按建立的次序編號),第i個單鏈表中的結點表示依附於頂點vi的邊(對於有向圖是以頂點vi為尾的弧)。每個結點由兩個域組成:鄰接點域(adjvex),用以指示與vi鄰接的點在圖中的位置,鏈域(nextarc)用以指向依附於頂點vi的下一條邊所對應的結點。如果用鄰接表存放網(帶權圖)的信息,則還需要在結點中增加一個存放權值的域(info)。每個頂點的單鏈表中結點的個數即為該頂點的出度(與該頂點連接的邊的總數)。無論是存儲圖或網,都需要在每個單鏈表前設一表頭結點,這些表頭結點的第一個域data用於存放結點vi的編號i,第二個域firstarc用於指向鏈表中第一個結點。[編輯]圖的遍歷圖的遍歷方法有深度優先搜索法和廣度(寬度)優先搜索法。深度優先搜索法是樹的先根遍歷的推廣,它的基本思想是:從圖G的某個頂點v0出發,訪問v0,然後選擇一個與v0相鄰且沒被訪問過的頂點vi訪問,再從vi出發選擇一個與vi相鄰且未被訪問的頂點vj進行訪問,依次繼續。如果當前被訪問過的頂點的所有鄰接頂點都已被訪問,則退回到已被訪問的頂點序列中最後一個擁有未被訪問的相鄰頂點的頂點w,從w出發按同樣的方法向前遍歷,直到圖中所有頂點都被訪問。其遞歸演算法如下:Boolean visited[MAX_VERTEX_NUM]; //訪問標志數組Status (*VisitFunc)(int v); //VisitFunc是訪問函數,對圖的每個頂點調用該函數void DFSTraverse (Graph G, Status(*Visit)(int v)){ VisitFunc = Visit; for(v=0; v<G.vexnum; ++v) visited[v] = FALSE; //訪問標志數組初始化 for(v=0; v<G.vexnum; ++v) if(!visited[v]) DFS(G, v); //對尚未訪問的頂點調用DFS}void DFS(Graph G, int v){ //從第v個頂點出發遞歸地深度優先遍歷圖Gvisited[v]=TRUE; VisitFunc(v); //訪問第v個頂點for(w=FirstAdjVex(G,v); w>=0; w=NextAdjVex(G,v,w))//FirstAdjVex返回v的第一個鄰接頂點,若頂點在G中沒有鄰接頂點,則返回空(0),//若w是v的鄰接頂點,NextAdjVex返回v的(相對於w的)下一個鄰接頂點。//若w是v的最後一個鄰接點,則返回空(0)。 if(!visited[w]) DFS(G, w); //對v的尚未訪問的鄰接頂點w調用DFS}圖的廣度優先搜索是樹的按層次遍歷的推廣,它的基本思想是:首先訪問初始點vi,並將其標記為已訪問過,接著訪問vi的所有未被訪問過的鄰接點vi1,vi2, …, vi t,並均標記已訪問過,然後再按照vi1,vi2, …, vi t的次序,訪問每一個頂點的所有未被訪問過的鄰接點,並均標記為已訪問過,依次類推,直到圖中所有和初始點vi有路徑相通的頂點都被訪問過為止。其非遞歸演算法如下:Boolean visited[MAX_VERTEX_NUM]; //訪問標志數組Status (*VisitFunc)(int v); //VisitFunc是訪問函數,對圖的每個頂點調用該函數void BFSTraverse (Graph G, Status(*Visit)(int v)){ VisitFunc = Visit;for(v=0; v<G.vexnum, ++v) visited[v] = FALSE; initQueue(Q); //置空輔助隊列Q for(v=0; v<G.vexnum; ++v) if(!visited[v]){ visited[v]=TRUE; VisitFunc(v); EnQueue(Q, v); //v入隊列 while(!QueueEmpty(Q)){ DeQueue(Q, u); //隊頭元素出隊並置為u for(w=FirstAdjVex(G,u); w>=0; w=NextAdjVex(G,u,w)) if(!Visited[w]){ //w為u的尚未訪問的鄰接頂點 Visited[w]=TRUE; VisitFunc(w); EnQueue(Q, w); } } }}
[編輯]圖的重要類型樹平面圖連通圖強連通圖有向無環圖AOV網AOE網完全圖:每一對不同頂點間都有邊相連的的圖,記作Kn。二分圖:頂集,且每一條邊都有一個頂點在X中,而另一個頂點在Y中。完全二分圖:二分圖G中若任意兩個X和Y中的頂點都有邊相連。若,則圖G記作Km,n。正則圖:如果圖中所有頂點的度皆相等,則此圖稱為正則圖歐拉圖:存在經過所有邊一次(可以多次經過點)的路徑的圖哈密頓圖:存在經過所有點一次的路徑的圖

❽ 圖的定義與存儲

圖狀結構是一種比樹形結構更復雜的非線性結構。在樹形結構中,結點間具有分支層次關系,每一層上的結點只能和上一層的至多一個結點相關,但可能和下一層的多個結點相關。而在圖狀結構中,任意兩個結點之間都可能相關,即結點之間的鄰接關系可以是任意的。因此,圖是 比樹更一般、更復雜的非線性結構,常被用於描述各種復雜的數據對象,在自然科學、社會科學和人文科學等許多領域有著非常廣泛的應用。

圖(Graph)是由非空的頂點集合和一個描述頂點之間的關系——邊(或者弧)的集合組成的,其形式化定義為:G=(V,E)、V={v1|v1包含data object}、E={(v1,vj)|(vi,vj 包含V^P(vj,vj)。其中,G表示一個圖,V是圖G中頂點的集合,E是圖G中邊的集合,集合E中P(vi,vj)表示頂點vi和頂點vj之間有一條直接連線,即偶對(v1,vj)表示一條邊。如:G2=(V2,E2)、V2={v1,v2,v3,v4}、E2={<v1,v2>,<v1,v3>,<v3,v4>,<v4,v1>}。

1、無向圖:在一個圖中,如果任意兩個頂點構成的偶對(vi,vj)包含E是無序的,即頂點之間的連線是沒有方向的,則稱該圖為無向圖。

2、有向圖:在一個圖中,如果任意兩個頂點構成的偶對<vj,vj>包含E是有序的(有序對常常用尖括弧「<>」表示),即頂點之間的連線是有方向的,則稱該圖為有向圖。

6、頂點的度、入度、出度:頂點的度(Degree)是指依附於某頂點v的邊數,通常記為TD(v)。頂點v的入度是指以頂點v為終點的弧的數目,記為ID(V);出度是指以頂點v為始點的弧的數目,記為OD(V)。有TD(V)=ID(v)+OD(v)。

7、邊的權、網:與邊有關的數據信息稱為權(Weight)。在實際應用中,權值可以有某種含義。例如,在一個反映城市交通線路的圖中,邊上的權值可以表示該條線路的長度或等級;對於一個電子線路圖,邊上的權值可以表示兩個端點之間的電阻、電流或電壓值;對於反映工程進度的圖而言,邊上的權值可以表示從前一個工程到後一個工程所需要的時間或其他代價等。邊上帶權的圖稱為網或網路(network)。

8、路徑、路徑長度:頂點vp到頂點vq之間的路徑(path)是指頂點序列vp、vi1、vi2、···、vim、vq。其中,(vp,vi1)、(vi1,vi2)、···、(vim,vq)分別為圖中的邊。路徑上邊的數目稱為路徑長度。

9、簡單路徑、迴路、簡單迴路:序列中頂點不重復出現的路徑稱為簡單路徑。路徑中第一個頂點與最後一個頂點相同的 路徑稱為迴路或環(Cycle)。除第一個頂點與最後一個頂點之外,其他頂點不重復出現的迴路稱為簡單迴路,或者簡單環。

10、子圖:對於圖G=(V,E),G'=(V',E'),若存在 V'是V的子集, E'是E的子集,則稱圖 G'是G的的一個子圖。

11、連通、連通圖、連通分量:在無向圖中,如果從一個頂點vi到另一個頂點vj(i=!j)存在路徑,則稱頂點vi和vj是連通的。如果圖中任意兩個頂點都是連通的,則稱該圖是連通圖。無向圖的極大連通子圖稱為連通分量,極大連通子圖是指在保證連通與子圖的條件下,包含原圖中所有的頂點與邊。 如下圖:

12、強連通圖、強連通分量:對於有向圖來說,若圖中任意一對頂點vi和vj(i=!j)均存在從一個頂點vi到另一個頂點vj和從vj到vi的路徑,則稱該有向圖是強連通圖。有向圖的極大強連通子圖稱為強連通分量,極大強連通子圖的含義同上。

13、生成樹:所謂連通圖G的生成樹,是G的包含其全部n個頂點的一個極小連通子圖,所謂極小連通子圖是指在包含所有頂點且保證連通的前提下盡可能少地包含原圖中的邊。生成樹必定包含且僅包含連通圖G的n-1條邊。在生成樹中添加任意一條屬於原圖中的邊必定會產生迴路,因為新添加的邊使其所依附的兩個頂點之間有了第二條路徑。若生成樹中減少任意一條邊,則必然成為非連通的。

14、生成森林:在非連通圖中,由每個連通分量都可得到一個極小連通子圖,即一棵生成樹。這些連通分量的生成樹就組成了一個非連通圖的生成森林。

將上圖存儲到計算機中,請設計一個數據結構並將其合理存儲起來?

所謂鄰接矩陣(Adjacency Matrix)的存儲結構,就是用一維數組存儲圖中的頂點信息,用矩陣表示圖中各頂點的信息,用矩陣表示圖中各頂點的信息,用矩陣表示圖中各頂點之間的鄰接關系。假設圖G=(V,E)有n個確定的頂點,即V ={v0,v1,···,vn-1},則表示G中各頂點相鄰關系的矩陣為一個n×n的矩陣,矩陣的元素為:

A[i][j]={1,若(vi,vj)或<vi,vj>是E(G)中的邊 ;2,若(vi,vj)或<vi,vj>不是E(G)中的邊。

若G是網,則鄰接矩陣可定義為:

A[i][j]={wij,若(vi,vj)或<vi,vj>是E(G)中的邊 ;0或&,若(vi,vj)或<vi,vj>不是E(G)中的邊。

(1)無向圖的鄰接矩陣一定是一個對稱矩陣。因此,在具體存放鄰接矩陣時只需存放上或下三角矩陣的元素即可。

(2)對於無向圖,鄰接矩陣的第i行或第i列非零元素或非&元素的個數正好是第i個頂點的度TD(vi)。

(3)對於有向圖,鄰接矩陣的第i行貨第i列非零元素或非&元素的個數正好是第i個頂點的出度OD(vi)或如度ID(vi)。

(4)用鄰接矩陣方法存儲圖,很容易確定圖中任意兩個頂點之間是否有邊相連;但是,要確定圖中有多少條邊,則必須按行、按列對每個元素進行檢測,所花費的時間代價很大。這是用鄰接矩陣存儲圖的局限性。

在實際應用鄰接矩陣存儲圖時,除了用一個二維數組存儲用於表示頂點間相鄰關系的鄰接矩陣外,還需用一個一維數組來存儲頂點信息,另外,還有圖的頂點樹和邊樹。故可將其形式描述如下:

鄰接表(Adjacency List)是圖的一種順序存儲於鏈式存儲結合的存儲方法。鄰接表表示法類似於樹的孩子鏈表表示法。就是對於圖G中的每個頂點vi,將所有鄰接於vi的頂點vj鏈成一個單鏈表,這個單鏈表就稱為頂點vi的鄰接表,再將所有頂點的鄰接表表頭放到數組中,就構成了圖鄰接表。

在鄰接表表示中有兩種結點結構:一種是頂點表的結點結構,它由頂點域(vertex)和指向第一條鄰接邊的指針域(firstedge)構成。另一種是邊表即鄰接表結點,它由鄰接點域(adjvex)和指向下一條鄰接邊的指針域(next)構成。對於網的邊表需再增設一個存儲邊上的信息(如權值等)的域(info)。

熱點內容
netty實現ftp 發布:2025-04-05 17:35:54 瀏覽:88
列印菱形java 發布:2025-04-05 17:35:53 瀏覽:907
等響演算法 發布:2025-04-05 17:24:17 瀏覽:998
演算法精編 發布:2025-04-05 17:17:03 瀏覽:354
虐殺原形2和熱血無賴哪個配置高 發布:2025-04-05 17:09:23 瀏覽:610
計算機常用演算法 發布:2025-04-05 17:07:54 瀏覽:65
天選2密碼在哪裡設置 發布:2025-04-05 16:36:28 瀏覽:87
目前什麼安卓手機續航能力最強 發布:2025-04-05 16:31:22 瀏覽:598
夢幻壓縮打造什麼意思 發布:2025-04-05 16:28:55 瀏覽:235
避難間里都需配置哪些東西 發布:2025-04-05 16:14:40 瀏覽:436