DFS和BFS
1:图的DFS=树的先根遍历=二叉树的先序遍历。
从无向图任意结点出发进行一次DFS即可访问所有结点,则该图是:连通图
判断一个有向图是否有环亦可用DFS
2:基于邻接矩阵的DFS时间复杂度:O(n^2),基于邻接表的DFS时间复杂度:O(n+e)
3:图的BFS=树的层次遍历,能够遍历所有与该结点连通的顶点,可求无向图的所有连通分量
4:基于邻接矩阵的BFS是唯一的,基于邻接表的BFS不唯一
连通性
连通度:在连通图上至少删除k个顶点才能破坏图的连通性,称k为该图的连通度
最小生成树
定义:不允许有环,从n个顶点的连通图选取n-1条权值最小的边
两种算法:Prim算法和Kruskal算法
任何一个连通图的最小生成树有一棵或者多棵,因为可能有多条权值相同的边
1:Prim:从某个顶点出发,选取与其连接的最小路径,再从被选的那个结点出发,重复以上操作,直到遍历完所有结点。
此时的图存储结构是邻接矩阵
Prin算法时间复杂度:O(n^2), 适用于稠密网
#define Max_Vex 6 //最大范围
#define LostType int
typedef char VertexType;//顶点名字的类型
typedef enum {
DG,DN,UDG,UDN//有向图,有向网,无向图 无向网
}GraphKing;
typedef struct ArcCell{
VRType adj;//弧或者边的权值等
InfoType *Info;//该弧相关信息的指针
}ArcCell,AdjMatrix[MAX_VERTEX_MUN][MAX_VERTEX_MUN];//该矩阵的每一个元素拥有其成员adj 和 *info
typedef struct MGraph{
VertexType vexs[MAX_VERTEX_MUN];// 比如说V1 V2 V3。。。。的类型
AdjMatrix arcs;//邻接矩阵
int vexnum,arcnum;//当前顶点数和弧数
GraphKing kind;
}MGraph,*MGraphLink;
typedef struct {
int adjvex;//顶点名
LostType Lowlost;
}Prim,Closedge[Max_Vex];
int Minnum(Closedge closedge){//进来 返回下一个结点;第K个结点 最小的那个
int i,j=0,min=100;
for(i=1;i<Max_Vex;i++){
if((closedge[i].Lowlost>0)&&(min>closedge[i].Lowlost)) {
min=closedge[i].Lowlost;
printf("选好的顶点%d权值%d",i,min);
j=i;//当前矩阵最小值的下标
}
}
return j;
}
void MiniSpanTree_PRIM(MGraph G){//最小生成树的普利姆算法
//暂时约定从第一个顶点进入(开始)
int i,k=0,j=0;Closedge closedge;
printf("入口的顶点%d",G.vexs[0]);
for(i=1;i<G.vexnum;i++){
closedge[i].adjvex=G.vexs[i];//顶点名 坐标
closedge[i].Lowlost =G.arcs[k][i].adj;//第一个顶点与其余各顶点(不包括第一个顶点,index从0开始)的权值
} //对于无向图来说,只用遍历一行(列)就能得到weigth
closedge[0].Lowlost=0;//入口入U集、、下次就不比较了
for(i=1;i<G.vexnum;++i) {
k=Minnum(closedge);//最小结点的序号
printf("---->%c",G.vexs[k]); //被选的顶点
closedge[k].Lowlost=0;//第k个顶点入U集合 下次就不用比较了
for(j=0;j<G.vexnum;++j){//更新closedge数组
if(G.arcs[k][j].adj<closedge[j].Lowlost){//重新更新closedge
closedge[j].adjvex=G.vexs[j];
closedge[j].Lowlost=G.arcs[k][j].adj;//权值
}
}
}
return 0;
}
2:Kruskal算法:第一步:多次选“两两权值最小且不重复的顶点相连”,如果总的顶点树目为奇数则余留一个等下次再选,第二步:重复第一步骤,直到变成连通图。
时间复杂度:O(elog2e),通常选并查集做辅助,选权值最小的原则:不能构成回路,适用于稀疏图