1图的定义
V1称为顶点。V1到V2在有向图中称为弧,在无向图中称为边。假设n为顶点的个数,则:
当有1/2 * n (n-1)条边的无向图称为完全图,
当有n*(n-1)条弧的有向图称为有向完全图。
有时图的边或弧具有与它相关的数,这种与图的边或弧相关的数叫做权。这些权可以表示从一个顶点到另一个顶点的距离或耗费。这种带全的图通常称为网。故而,亦有有向网、无向网。
2图的存储结构
存储结构表示法 | 图的种类 |
数组表示法 | 有向图、无向图 |
邻接表 | 有向图、无向图 |
十字链表 | 有向图 |
邻接多重表 | 无向图 |
/*数组存储结构*/
#define INFINITY INT_MAX
#define MAX_VERTEX_NUM 20 /*最大顶点个数*/
typedef enum {DG,DN,UDG,UDN}graph_kind;/*有向图,有向网,无向图,无向网*/
typedef int vr_type;
typedef char info_type;
typedef struct arc_cell
{
vr_type adj; /*顶点关系类型*/
info_type *info; /*该弧相关信息的指针*/
}arc_cell, adj_matrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedef char ver_tex_type;
typedef struct
{
ver_tex_type vexs[MAX_VERTEX_NUM];/*顶点向量*/
adj_matrix arcs; /*邻接矩阵*/
int vexnum, arcnum; /*图的当前顶点数和弧数*/
graph_kind kind; /*图的种类标志*/
}m_graph;
/*邻接表存储结构*/
#define MAX_VERTEX_NUM 20
typedef struct arc_node
{
int adjvex; /*该弧所指向的顶点的位置*/
struct arc_node *next_arc; /*指向下一条弧的指针*/
info_type *info; /*该弧相关信息的指针*/
}arc_node;
typedef struct v_node
{
ver_tex_type data; /*顶点信息*/
arc_node *first_arc; /*指向第一条依附该顶点的弧的指针*/
}v_node, adj_list[MAX_VERTEX_NUM];
typedef struct
{
adj_list vertices; /*图的当前顶点数和弧数*/
int vexnum, arcnum; /*图的种类标志*/
int kind;
}al_graph;
/*有向图的十字链表存储结构*/
#define MAX_VERTEX_NUM 20
typedef struct arc_box
{
int tailvex, headvex;
struct arc_box *hlink,*tlink;
info_type *info;
}arc_box;
typedef struct vex_node
{
ver_tex_type data;
arc_box *first_in, *first_out;/*分别指向该顶点的第一条入弧和出弧*/
}vex_node;
typedef struct
{
vex_node xlist[MAX_VERTEX_NUM];/*表头向量*/
int vexnum, arcnum; /*有向图的当前顶点数和弧数*/
}ol_graph;
/*无向图的邻接多重表存储结构*/
#define MAX_VERTEX_NUM 20
typedef enum{unvisited,visited}visit_if;
typedef struct ebox
{
visit_if mark; /*访问标记*/
int ivex,jvex; /*该边指向依附这两个顶点的下一条边*/
struct ebox *ilink,*jlink; /*该边的信息指针*/
info_type *info;
}ebox;
typedef struct vex_box
{
ver_tex_type data;
ebox *first_edge; /*指向第一条依附该顶点的边*/
}vex_box;
typedef struct
{
vex_box adjmulist[MAX_VERTEX_NUM];
int vexnum,edgenum; /*无向图的当前顶点数和边数*/
}aml_graph;
3图的遍历
图的遍历是树的遍历的推广,是按照某种规则(或次序)访问图中各顶点依次且仅一次的操作,亦是将网络结构按某种规则线性化的过程。
由于图存在回路,为区别一顶点是否被访问过和避免顶点被多次访问,在遍历过程中,应记下每个访问过的顶点,即每个顶点对应有一个标志位,初始为False,一旦该顶点被访问,就将其置为True,以后若又碰到该顶点时,视其标志的状态,而决定是否对其访问。
1深度优先搜索(Depth_First Search,简称DFS,类似树的先根遍历)
思路:
类似树的先根遍历。设初始化时,图中各顶点均未被访问,从图中某个顶点(设为V0)出发,访问V0,然后搜索V0的一个邻接点Vi,若Vi未被访问,则访问之,在 搜索Vi的一个邻接点(深度优先)。若某顶点的邻接点全部访问完毕,则回溯(Backtracking)到它的上一顶点,然后再从此顶点又按深度优先的方法搜索下去,直到能访问的顶点都访问完毕为止。
2广度优先搜索(Breadth_First Search,简称BFS,类似树的层序遍历)
思路:
类似树的按层次遍历。初始时,图中各顶点均未被访问,从图中某顶点(V0)出发,访问V0,并依次访问V0的各邻接点(广度优先)。然后,分别从这些被访问过的顶点出发,扔仍按照广度优先的策略搜索其它顶点,直到能访问的顶点都访问完毕为止。为控制广度优先的正确搜索,要用到队列技术,即访问完一个顶点后,让该顶点的序号进队。然后取相应队头(出队),考察访问过的顶点的各邻接点,将未访问过的邻接点访问后再依次进队,直到队空为止。