有向圖的十字鏈表
對於有向圖來說,鄰接表是有缺陷的,關心了出度問題,想了解入度就必須要遍歷整個圖才能知道,反之,逆鄰接表解決了入度的情況。
把鄰接表與逆鄰接表結合起來,即有向圖的一種存儲方法十字鏈表(Orthogonal List)。
我們重新定義頂點表結構
firstin表示入邊表頭指針,指向該頂點的入邊表中第一個結點;
firstout表示出邊表頭指針,指向該頂點的出邊表中第一個結點;
重新定義了邊表結點結構
其中
tailvex是指弧起點在頂點的下標,
headvex是指弧終點在頂點表中的下標,
headlink是指入邊表指針域,指向終點相同的一下條邊
taillink是指出邊表指針域,指向起點相同的下一條邊。
如果是網,還可以再增加一個weight域來存儲權值。
如圖對於這樣的一個有向圖,構建如下的十字鏈表
對於十字鏈表的一些認識:
1.表頭結點即頂點結點,與鄰接表一樣是順序存儲。
2.對於每個頂點結點之后是與之相關聯的弧結點(該弧結點中存有弧頭、弧尾),而鄰接表則是一些與頂點結點相連接的點。
3.從每個頂點結點開始有兩條鏈表,一條是以該頂點結點為弧頭的鏈表,一條是以該頂點結點為弧尾的鏈表。
4.對於其中的每一條鏈表必然是從頂點結點開始,直到與之相關的弧結點鏈域headlink和taillink為空是結束,構成一條完整的鏈表。
十字鏈表存儲結構:
typedef struct ArcBox // 弧的結構表示 { int tailvex, headvex; InfoType *info; struct ArcBox *hlink, *tlink; } VexNode; typedef struct VexNode // 頂點的結構表示 { VertexType data; ArcBox *firstin, *firstout; } VexNode;
typedef struct { VexNode xlist[MAX_VERTEX_NUM];// 頂點結點(表頭向量) int vexnum, arcnum;//有向圖的當前頂點數和弧數 } OLGraph;
十字鏈表的好處就是因為把鄰接表和逆鄰接表整合在一起,這樣既容易找到vi為尾的弧,也容易打到以vi為頭的弧,因而容易求得頂點的出度和入度。而且它除了結構復雜一點燃上,其實創建圖的算法的時間復雜度與鄰接表相同,因此,在有向圖的應用中,十字鏈表是非常好的數據結構模型。
無向圖的鄰接多重表
對於無向圖的邊操作,如下圖要刪除(v0,v2)這條邊要做
需要對鄰接表結構中右邊表的陰影兩個結點進行刪除操作,顯然比較煩瑣
因此,我們也仿照十字鏈表的方式對邊表結構進行一些改造,也許就可避免剛才的問題。
重新定義邊表結構:
其中mark是標志域,用於標記該條邊是否訪問過。ivex和jvex是與某條邊依附的兩個頂點在頂點表中的下標。ilink指向依附頂點ivex的下條邊,jlink指向依附頂點的下一條邊。這就是鄰接多重表結構。
對於頂點結構不變,也是用一個結點表示,由存儲與該結點信息相關的域date和指示第一條依附於該結點的邊的域firstedge構成。
我們來看結構示意圖的繪制過程,理解了它是如何連線的,也就是理解鄰接多重表構造原理了。
對於鄰接多重表的一些認識:
1.表頭結點即頂點結點,與鄰接表一樣是順序存儲。
2.對於每個頂點結點之后是與之相關聯的邊結點(與該頂點結點相連的邊),而鄰接表則是一些與頂點結點相連接的點。
3.從每個頂點結點開始有一條鏈表,這條鏈表將所有與該頂點相連的邊都連接了起來。
4.鄰接多重表中邊結點的個數就是無向圖中邊的數量,又因為無向圖中的邊必然連接兩個頂點,所以便邊結點結構中的ilink和jlink會連接兩個不同的鏈表。
鄰接多重表的存儲結構:
typedef struct Ebox { VisitIf mark; // 訪問標記 int ivex, jvex;//該邊依附的兩個頂點的位置 struct EBox *ilink, *jlink; InfoType *info; // 該邊信息指針 } EBox; typedef struct VexBox { VertexType data; EBox *firstedge; // 指向第一條依附該頂點的邊 } VexBox; typedef struct // 鄰接多重表 { VexBox adjmulist[MAX_VERTEX_NUM]; int vexnum, edgenum; } AMLGraph;