#define MAX_VERTEX_NUM 20
#define INFINITY 32768
typedef enum
{
DG,
DN,
UDG,
UDN
} GraphKind;
typedef char VertexData;
typedef struct ArcNode
{
AdjType adj;
OtherInfo info;
} ArcNode;
typedef struct
{
VertexData vertex[MAX_VERTEX_NUM];
ArcNode arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
int vexnum, arcnum;
GraphKind kind;
} AdjMatrix;
int LocateVertex(AdjMatrix *G, VertexData v)
{
int j = Error, k;
for (k = 0; k < G->vexnum; k++)
if (G->vertex[k] == v)
{
j = k;
break;
}
return (j);
}
int CreateDN(AdjMatrix *G)
{
int i, j, k, weight;
VertexData v1, v2;
scanf("%d,%d", &G->arcnum, &G->vexnum);
for (i = 0; i < G->vexnum; i++)
for (j = 0; j < G->vexnum; j++)
G->arcs[i][j].adj = INFINITY;
for (i = 0; i < G->vexnum; i++)
scanf("%c", &G->vertex[i]);
for (k = 0; k < G->arcnum; k++)
{
scanf("%c,%c,%d", &v1, &v2, &weight);
i = LocateVex_M(G, v1);
j = LocateVex_M(G, v2);
G->arcs[i][j].adj = weight;
}
return (Ok);
}
该算法的时间复杂度为 O(n2+e×n),其中 O(n2)时间耗费在对二维数组 arcs 的每个分量的 arj 域初始化赋值上。O(e×n)的时间耗费在有向网中边权的赋值上
(实际上是一种链式存储结构)
如下图所示分别是图 G1、G2 邻接表表示示例,其中边表中顶点无顺序要求。
#define MAX_VERTEX_NUM 20
typedef enum
{
DG,
DN,
UDG,
UDN
} GraphKind;
typedef struct ArcNode
{
int adjvex;
struct ArcNode *nextarc;
OtherInfo info;
} ArcNode;
typedef struct VertexNode
{
VertexData data;
ArcNode *firstarc;
} VertexNode;
typedef struct
{
VertexNode vertex[MAX_VERTEX_NUM];
int vexnum, arcnum;
GraphKind kind;
} AdjList;
十字链表(Orthogonal List)是有向图的另一种链式存储结构。可以把它看成是将有向图的邻接表和逆邻接表结合起来形成的一种链表。有向图中的每一条弧对应十字链表中的一个弧结点,同时有向图中的每个顶点在十字链表中对应有一个 结点,叫做顶点结点。这两类结点结构如下图所示
例如:有向图 G1 的十字链表表示如下图所示。若有向图是稀疏图,则它的 邻接矩阵一定是稀疏矩阵,这时该图的十字链表表示法可以看成是其邻接矩阵的 链表表示法。只是在图的十字链表表示法中,弧结点所在的链表不是循环链表且 结点之间相对位置自然形成,不一定按顶点序号有序。另外,表头结点即顶点结 点,它们之间并非循环链式连接,而是顺序存储。
#define MAX_VERTEX_NUM 20
typedef enum
{
DG,
DN,
UDG,
UDN
} GraphKind;
typedef struct ArcNode
{
int tailvex, headvex;
struct ArcNode *hlink, *tlink;
} ArcNode;
typedef struct VertexNode
{
VertexData data;
ArcNode *firstin, *firstout;
tailvex
} VertexNode;
typedef struct
{
VertexNode vertex[MAX_VERTEX_NUM];
int vexnum, arcnum;
GraphKind kind;
} OrthList;
void CrtOrthList(OrthList *g)
{
scanf(“% d, % d”, &n, &e);
g->vexnum = n;
g->arcnum = e;
for (i = 0; i < n; i++)
{
scanf(“% c”, &(g->vertex[i].data));
g->vertex[i].firstin = NULL;
g->vertex[i].firsout = NULL;
}
for (k = 0; k < e; k++)
{
scanf(“% c, % c”, &vt, &vh);
i = LocateVertex(g,vt);
j = LocateVertex(g,vh);
p = (ArcNode *)malloc(sizeof(ArcNode));
p->tailvex = I;
p->headvex = j;
p->tlink = g->vertex[i].firstout;
g->vertex[i].firstout = p;
p->hlink = g->vertex[j].firstin;
g->vertex[j].firstin = p;
}
}
在十字链表中既能够很容易地找到以 vi 为尾的弧,也能够容易地找到以 vi 为头的弧,因此对于有向图,若采用十字链表作为存储结构,则很容易求出顶点 vi的度。此外,为有向图建立一个邻接表的算法和建立一个十字链表的算法的时 间复杂度是相同的。所以,在某些有向图的应用中,十字链表表示法更为合适
#define MAX_VERTEX_NUM 20
typedef struct EdgeNode
{
int mark, ivex, jvex;
struct EdgeNode *ilink, *jlink;
} EdgeNode;
typedef struct
{
VertexData data;
EdgeNode *firstedge;
} VertexNode;
typedef struct
{
VertexNode vertex[MAX_VERTEX_NUM];
Int vexnum, arcnum;
GraphKind kind;
} AdjMultiList;