图的连通性

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);
 }
 
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值