图的存储
一.邻接矩阵
对具有N个结点的图构造一个N*N的矩阵,矩阵数组的下标存储结点和相应顶点的位置,数组的值即为每两个邻接顶点的边的权值。
邻接矩阵可以表示有向或无向图,当两个顶点不邻接相通时我们可以将数组权值赋为0或0x3f3f3f3f(趋近无穷大值又不会溢出)。
//邻接矩阵
typedef struct
{
char vexs[MAXSIZE];
int arcs[MAXSIZE][MAXSIZE];
int vexnum,arcnum;
}AMGraph;
缺点:不便于增加和删除顶点,不便于统计边的数目,时间复杂度高,空间复杂度高,对于稀疏图而言十分浪费空间。
时间复杂度:O(n^2)
空间复杂度:O(n^2)
二.邻接表
邻接表:每个顶点建立一个链表,对无向图来说用于存放该顶点邻接的顶点,对有向图来说便是存放该顶点通向的邻接顶点。
//邻接表
typedef struct ArcNode
{
int adj;
struct ArcNode*next;
}ArcNode;
typedef struct VNode
{
int data;
ArcNode *First;
}VNode,AdjList[MAXSIZE];
typedef struct
{
AdjList ver;
int vexnum,arcnum;
}ALGraph;
逆邻接表:每个顶点建立一个链表,存放通向该顶点的邻接顶点。
十字链表:可以看作正邻接表和逆邻接表的结合,每个顶点和其结点度多设置一个指针域来存放入度。
//十字链表
typedef struct ArcBox
{
int head,tail;
struct ArcBox *h,*t;
}ArcBox;
typedef struct VexNode
{
int data;
ArcBox *firstin,*firstout;
}VexNode;
typedef struct
{
VexNode XList[MAXSIZE];
int vexnum,arcnum;
}OlGragh;
十字链表、邻接表和逆邻接表,顶点n,边e:
时间复杂度:O(n+e)
空间复杂度:O(n+e)
三.邻接多重表
邻接多重表是无向图的另一种链式存储结构,类似于十字链表;虽然邻接表是无向图的一种有效的存储结构,但当对已被搜索的边做记号或删除一条边时需要找到一条边的两个顶点,所以在对无向表进行一类操作时更适合采用邻接多重链表。
//邻接多重表
typedef enum{unvisited,visited} VisitIf;
typedef struct EBox
{
VisitIf mark;
int ivex,jvex;
struct EBox *iLink,*jLink;
}EBox;
typedef struct VexBox
{
int data;
EBox *Firstedge;
}VexBox;
typedef struct
{
VexBox AList[MAXSIZE];
int vexnum,edgenum;
}AMLGraph;
图的存储应根据实际需要选择最合适的存储结构。