java十字链表存储,图的十字链表存储结构
前面介紹了圖的鄰接表存儲法,本節(jié)繼續(xù)講解圖的另一種鏈式存儲結(jié)構(gòu)——十字鏈表法。
與鄰接表不同,十字鏈表法僅適用于存儲有向圖和有向網(wǎng)。不僅如此,十字鏈表法還改善了鄰接表計算圖中頂點入度的問題。
十字鏈表存儲有向圖(網(wǎng))的方式與鄰接表有一些相同,都以圖(網(wǎng))中各頂點為首元節(jié)點建立多條鏈表,同時為了便于管理,還將所有鏈表的首元節(jié)點存儲到同一數(shù)組(或鏈表)中。
其中,建立個各個鏈表中用于存儲頂點的首元節(jié)點結(jié)構(gòu)如圖 1 所示:
圖 1 十字鏈表中首元節(jié)點結(jié)構(gòu)示意圖
從圖 1 可以看出,首元節(jié)點中有一個數(shù)據(jù)域和兩個指針域(分別用 firstin 和 firstout 表示):
firstin 指針用于連接以當前頂點為弧頭的其他頂點構(gòu)成的鏈表;
firstout 指針用于連接以當前頂點為弧尾的其他頂點構(gòu)成的鏈表;
data 用于存儲該頂點中的數(shù)據(jù);
由此可以看出,十字鏈表實質(zhì)上就是為每個頂點建立兩個鏈表,分別存儲以該頂點為弧頭的所有頂點和以該頂點為弧尾的所有頂點。
注意,存儲圖的十字鏈表中,各鏈表中首元節(jié)點與其他節(jié)點的結(jié)構(gòu)并不相同,圖 1 所示僅是十字鏈表中首元節(jié)點的結(jié)構(gòu),鏈表中其他普通節(jié)點的結(jié)構(gòu)如圖 2 所示:
圖 2 十字鏈表中普通節(jié)點的結(jié)構(gòu)示意圖
從圖 2 中可以看出,十字鏈表中普通節(jié)點的存儲分為 5 部分內(nèi)容,它們各自的作用是:
tailvex 用于存儲以首元節(jié)點為弧尾的頂點位于數(shù)組中的位置下標;
headvex 用于存儲以首元節(jié)點為弧頭的頂點位于數(shù)組中的位置下標;
hlink 指針:用于鏈接下一個存儲以首元節(jié)點為弧頭的頂點的節(jié)點;
tlink 指針:用于鏈接下一個存儲以首元節(jié)點為弧尾的頂點的節(jié)點;
info 指針:用于存儲與該頂點相關(guān)的信息,例如量頂點之間的權(quán)值;
比如說,用十字鏈表存儲圖 3a) 中的有向圖,存儲狀態(tài)如圖 3b) 所示:
圖 3 十字鏈表存儲有向圖示意圖
拿圖 3 中的頂點 V1 來說,通過構(gòu)建好的十字鏈表得知,以該頂點為弧頭的頂點只有存儲在數(shù)組中第 3 位置的 V4(因此該頂點的入度為 1),而以該頂點為弧尾的頂點有兩個,分別為存儲數(shù)組第 1 位置的 V2 和第 2 位置的 V3(因此該頂點的出度為 2)。
對于圖 3 各個鏈表中節(jié)點來說,由于表示的都是該頂點的出度或者入度,因此沒有先后次序之分。
圖 3 中十字鏈表的構(gòu)建過程轉(zhuǎn)化為 C 語言代碼為:
#define MAX_VERTEX_NUM 20
#define InfoType int//圖中弧包含信息的數(shù)據(jù)類型
#define VertexType int
typedef struct ArcBox{
int tailvex,headvex;//弧尾、弧頭對應頂點在數(shù)組中的位置下標
struct ArcBox *hlik,*tlink;//分別指向弧頭相同和弧尾相同的下一個弧
InfoType *info;//存儲弧相關(guān)信息的指針
}ArcBox;
typedef struct VexNode{
VertexType data;//頂點的數(shù)據(jù)域
ArcBox *firstin,*firstout;//指向以該頂點為弧頭和弧尾的鏈表首個結(jié)點
}VexNode;
typedef struct {
VexNode xlist[MAX_VERTEX_NUM];//存儲頂點的一維數(shù)組
int vexnum,arcnum;//記錄圖的頂點數(shù)和弧數(shù)
}OLGraph;
int LocateVex(OLGraph * G,VertexType v){
int i=0;
//遍歷一維數(shù)組,找到變量v
for (; ivexnum; i++) {
if (G->xlist[i].data==v) {
break;
}
}
//如果找不到,輸出提示語句,返回 -1
if (i>G->vexnum) {
printf("no such vertex.\n");
return -1;
}
return i;
}
//構(gòu)建十字鏈表函數(shù)
void CreateDG(OLGraph *G){
//輸入有向圖的頂點數(shù)和弧數(shù)
scanf("%d,%d",&(G->vexnum),&(G->arcnum));
//使用一維數(shù)組存儲頂點數(shù)據(jù),初始化指針域為NULL
for (int i=0; ivexnum; i++) {
scanf("%d",&(G->xlist[i].data));
G->xlist[i].firstin=NULL;
G->xlist[i].firstout=NULL;
}
//構(gòu)建十字鏈表
for (int k=0;karcnum; k++) {
int v1,v2;
scanf("%d,%d",&v1,&v2);
//確定v1、v2在數(shù)組中的位置下標
int i=LocateVex(G, v1);
int j=LocateVex(G, v2);
//建立弧的結(jié)點
ArcBox * p=(ArcBox*)malloc(sizeof(ArcBox));
p->tailvex=i;
p->headvex=j;
//采用頭插法插入新的p結(jié)點
p->hlik=G->xlist[j].firstin;
p->tlink=G->xlist[i].firstout;
G->xlist[j].firstin=G->xlist[i].firstout=p;
}
}
提示,代碼中新節(jié)點的插入采用的是頭插法。
總結(jié)
以上是生活随笔為你收集整理的java十字链表存储,图的十字链表存储结构的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 在Oracle里,表的别名不能用as,列
- 下一篇: WeMos下实现小车避障与手机控制