1.无向图的连通性
假设以孩子兄弟链表表示森林的存储结构
typedef struct CSNode{
ElemType data;
struct CSNode *firstchild , *nextsibling;
}CSNode,*CSTree;
尝试用深度优先生成非连通图的森林:
算法基本思路:
//生成森林的每一棵树的根节点通过nextsibling组成的链表,然后分别生成以这些结点为root的子树,显然是森林中是可以有多棵子树的。
基本思路:从0开始的第一层遍历,得到的结点将会是生成森林的每一棵子树的根节点,需要将这些根节点连成一个链表。森林的根结点T将第一个结点(0结点),其他结点都作为上一个根节点的nextsibling,所以需要用q来记录上一个邻接点。
至于每一个根节点对应的子树的生成,调用DFSTree来完成。
由于森林中可能有多个子树,所以讲算法拆分为,FDSForest生成森林,DFSTree生成每一棵树,生成树可以递归调用的;
void DFSForest(Graph G,CSTree *T)
{
T = NULL;
for(int i = 0; i < vexnum; ++i) visited[v] = FALSE;
for(int i = 0; i < vexnum; ++i){
if(!visited[v]){
p = (CSTree)malloc(sizeof(CSNode));
*p = {GetVex(G,v),NULL,NULL};
if(!T) T = p;
else q->nextsibling = p;
q = p;
DFSTree(G,v,p);
}
}
}
//递归方法从第v个结点开始森林子树的生成
基本思路:对于任意一个结点,遍历它的所有未被访问过的邻接点:
如果第一邻接点,让它作为自己的firstchild **需要first来标记第一孩子
否则,让它作为上一个孩子的nextsibling, **需要q来记录上一结点
递归使用,让它的邻接点继续生成它们的子树
void DFSTree(Graph g,int v,CSTree *T){
visited[v] = TRUE;
first = TRUE;
for(w = FirstAdfVex(G,v); v; w = NextAdjVex(G , v, w)){
if(!visited[w]){
p = (CSTree)malloc(sizeof(CSNode));
*p = {GetVex(G,w),NULL,NULL};
if(first){ T->firstchild = p; first = FALSE;}
else{
q->nextsibling = p;
q = p;
}
DFSTree(G,w,q);
}
}
}
2.有向图的强连通分量
强连通分量:有向图中的极大强连通子图,子图中任意两点间存在路径
假设有向图使用的是十字链表的存储方法:(十字链表是无向图邻接表和逆邻接表的结合,添加了firstin)
数据结构:
typedef struct AcrBox{
int tailvex , headvex;
struct AcrBox *hlink, *tlink;
InfoType *info;
}ArcBox;
typedef struct VexNode{
VertexType data;
VerBox *firstin, *firstout; //指向顶点的第一条入弧和出弧
}VexNode;
typedef struct{
VexNode xlist[MAX_VERTEX_NUM]; //表头向量
int vexnum , arcnum;
}OLGraph;
深度优先搜索遍历方法:
1.从顶点出发以弧尾方向进行深度优先搜索遍历,每当一次搜索完成DFS后,即finished[++count]中记录这个结点v,这个结点即是完成搜索的那个各节点。
finised数组记录的是所有以弧尾方向进行搜索时候所能到达的最远点。
2. 以finished数组为依据,
3.最小生成树
构造连通网的最小代价生成树(minimum cost spanning tree),一棵生成树的最小代价是树上各个边的代价之和。
MST性质:简而言之,就是其中必然包含着所有边中代价最小的那一条边。很多的算法就是基于这个性质的。
经典的算法是:prim算法和kruskal算法,基于MST性质。
prim算法:
N = {V,{E}}连通网 TE:N上最小生成树的边的集合 U为顶点集V的非零子集,E为所有的边的集合
算法从U = {u0} TE ={} 开始,循环开始:{
在所有u∈U v∈V-U的边(u,v)∈E中找出最小的边(u0,v0)并入TE中,同时v0并入到U中
}循环结束条件(U == V)
即 当所有的结点都被选,循环结束。
用邻接矩阵表示网再好不过:
#define INFINITY INT_MAX
#define MAX_VERTEX_NUM 20
typedef emun{DG,DN,AG,AN}GraphKind;
//顶点定义
typedef struct ArchCell{
VRTType adj; //顶点关系类型,对于无权图,用0、1表示是否邻接
对于有全图,用数值表示权值
InfoType *info; //
}ArcCell,AdjMarix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
//图的定义
typedef struct{
VertexType vexs[MAX_VERTEX_NUM]; //顶点信息
AdjMatrix arcs; //边或弧信息
int vexnum,arcnum;
GraphKind kind;
}MGraph;
//记录从顶点集U到V-U的代价最小的边的辅助数组定义
struct {
VertexType adjvex; //邻接点
VRType lowcost; //边上的权值
}closeEdge[MAX_VERTEX_NUM]
//从第u个顶点出发构造图G的最小生成树T,打印各条各条边
void MiniSpanTree_Prim(MGraph G,VertexType u){
k= LocateVex(G , u);
closeEdge[k].lowcost = 0;
for(j = 0; j < G.vexnum; ++j)
if(j != k) closeEdge[j] = {u, G.arcs[k][j].adj};
for(i = 1; i < G.vexnum; ++i){
k = minimum(closeEdge);
}
}