基础理论
图的基本定义 : 二元组 , 即结点和边( 弧 ) G = ( V, {E} )
有向图, 弧尾 --> 弧头
无向图, 边
无向完全图 n个结点 , 1/2n(n-1) 边, 就是任意两个结点都有边。
网 带权的图 , 这的权类似赫夫曼树的权.
子图 : G' = ( v', { E' } ) , v' 是v的子集, E' 是E的子集
邻接点 ( 互为) 两个结点有边
顶点v的度 : 无向图 相连的边 , 有向图 度 = 入度 + 出度
图的存储方法 :
1.数组存储表示( 邻接矩阵 )
/* 图 数组邻接矩阵 */
typedef struct ArcCell { /* 边的结构 */
VRType arcs; /* 相连 1, 不相连 0*/
InfoType *info; /* 边本身可能的信息 */
} ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VER_TEX_NUM];
typedef struct { /* 图的结构 */
VertexType vex[MAX_VERTEX_NUM]; /* 本身顶点存储的信息 */
AdjMatrix arcs; /* 顶点之间关系 */
int vexnum, arcnum; /* 顶点数和弧数 */
GraphKind kind; /* 图的种类标志 */
} MGraph;
说白了,就是用两个数组来存放图,一个是图的关系,即顶点之间的连接关系。另一个数组用来存放顶点内容。
2。邻接表
是图的一种链式存储结构,在邻接表中,对图中每个顶点建立一个单链表,第 i 个单链表中的节点表示依附于顶点vi 的边( 对有向图是以顶点vi为尾的弧 )
typedef struct ArcNode { /* 存储边的情况 */
int adjvex; /* 指示顶点在该顶点数组中的下标 */
struct ArcNode *nextarc; /* 跟此顶点相连的边 */
Infotype *info; /* 记录弧本身的信息,如权值 */
} ArcNode;
typedef struc VNode { /* 顶点结构 */
VertexType data; /* 顶点信息 */
ArcNode *firstarc; /* 第一条弧 */
} VNode, AdjList[MAX_VERTEX_NUM];
typedef struct { /* 图的结构 */
AdjList vertices; /* 图中顶点 */
int vexnum, arcnum; /* 顶点数和弧数 */
in kind; /* 图的标志 */
} ALGraph;
3。十字链表存储法 ( 有向图 )
typedef struct Arcbox { /* 弧的存储 */
int tailvex, headvex; /* 弧头, 弧尾节点在顶点数组中的下标 */
struct Arcbox *hlink, *tlink; /* 弧头,弧尾相同的链域 */
InfoType *info; /* 弧本身信息 */
} Arcbox;
typedef struct VexNode { /* 顶点存储 */
VertexType data; /* 顶点信息 */
Arcbox *firstin, *firstout; /* 第一个入弧,第一个出弧 */
} VexNode;
typedef struct { /* 图的存储 */
VexNode xlist[MAX_VERTEX_NUM]; /* 顶点数组 */
int vexnum, arcnum; /* 顶点数,弧数 */
} OLGraph;
4。邻接多重表 ( 无向图 ) ( 有点蒙 )
typedef struct EBox { /* 弧的存储 */
VisitIf mark; /* 标记是否被访问过 */
int ivex, jvex; /* 依附此弧的两个顶点在数组中的下标 */
struct EBox *ilink, *jlink; /* 分别指向这两个顶点的下一条边 */
infoTYpe *info; /* 弧本身的信息 */
} EBox;
typedef struct VexNode { /* 顶点存储 */
VertexType data; /* 顶点信息 */
EBox *firstedge; /* 第一个边 */
} VexBox;
typedef struct { /* 图的存储 */
vexBox adjmulist[MAX_VERTEX_NUM]; /* 顶点数组 */
int vexnum, arcnum; /* 顶点数,弧数 */
} AMLGraph;
图的遍历 ( 深度优先 , 广度优先 )
深度优先 : 类似于树饿先根遍历,根左右, 即访问到一个节点后,访问子节点a , 然后继续访问子节点的节点,而不是横向访问 a 的兄弟。
广度优先: 有点类似按层次访问,比如先访问节点a , 然后访问其全部子节点,完毕后,即,兄弟节点肯定要比子节点先被访问到.
例如 :
深度优先 : v1 -> v2 -> v4 -> v8 -> v5 -> v3 -> v6 -> v7
广度优先 : v1 -> v2 -> v3 -> v4 -> v5 -> v6 -> v7 -> v8