图 - suzhouzc/Data-Structure GitHub Wiki
-
无向完全图的边为:n(n-1)/2
-
极大连通子图:连通子图; 极小连通子图:生成树
-
邻接矩阵和邻接表的对比
-
(主要)深度优先遍历
void DFSTraverse(Graph G) { for (v=0 ; v < G.vexnum;++v) visited[v]=o; //初始化辅助数组 for (v=0 ; v< G.vexnum;++v) if(!visited[v]) DFS(G,V); //连通分量的个数=循环的次数 } void DFS(Graph G,int v) { visited[v]=1; Visit(v); //访问顶点v for(w=FirstAdjVex(G,v);w>=0;w=NextAdjVex(G,v,w)) if (!visited[w]) DFS(G,w); //访问v的邻接点 }
-
(递归)若以邻接矩阵法表示图,则DFS算法如下:
void DFS(MGraph G,int v) { //从v出发深度优先遍历 visited[v]; Visit(v); for(w=0;w<G.vexnum:w++) if(G.arcs[v][w].adj&&!visited[w]) DFS(G,w); }
-
(递归)若以邻接表发表示图,则DFS算法如下:
void DFS(ALGraph G,int v) {//从v出发的深度优先遍历 visited[v]=1; Visit(v); for (p=G.vertices[V].firstarc; p ;p=p->nextarc) if (!visited[p->adjvex]) DFS(G,p->adjvex); }
-
广度优先遍历非递归遍历图G,类似于数的层次遍历
void BFSTraverse(Graph G) { for (v=0;v<G.vexnum;++v) visited[v]=0; InitQueue(Q); for(v=0;v<G.vexnum:++v) if(!visited[v]) { visited[v]=1; Visit(v); EnQueue(Q,v); while(!QueueEmpty=0) { DeQueue(Q,u); for(w=FirstAdjVex(G,u);w>=0;w=NextAdjVex(G,u,w)) if(!visited[w]) {visited[w]=1;Visit(w);EnQueue(Q,w); } } } }//BFSTraverse
-
最短路径问题
-
求顶点u到其他顶点的最短路径(广度优先算法BFS)
void BFS_MIN_Distance(Graph G,int u){ for(i=0;i<G.vexnum;++i){ int d[i]=⚮; //初始化路径长度 int path[i]=-1; //最短路径从哪个顶点过来 } d[u]=0; visited[u]=TRUE; EnQueue(Q,u); while(!isEmpty(Q)){ DeQueue(Q,u); for(w=FirstNeighbor(G,u);w>=0;w=NextNeighbor(G,u,w)) if(!visited[w]){ //w为u尚未访问的邻接顶点 d[w]=d[u]+1; //路径长度加一 path[w]=u; //最短路径应从u到w visited[w]=TRUE; //设已访问标记 EnQueue(Q,w); //顶点w入队 } } }
-
迪杰斯特拉算法(最短路径)
Dijkstra算法不适合用于有负权值的带权图(跑毒、中途加电)
-
弗洛伊德算法(Floyd算法最短路径–动态规划思想)可解决负权值的问题
//--初始化矩阵A和path for (int k=0;k<n;k++){ //考虑以vk作为中转点 for (int i=0;i<n;i++){ --遍历整个矩阵,i为行号,j为列号 for(int j=0;j<n;j++){ if(A[i][j]>A[i][k]+A[k][j]) //以vk为中转点的路径更短 A[i][j]=A[i][k]+A[k][j]; //更新最短路径长度 path[i][j]=k; //中转点 } } }
-
AOV网(用顶点表示事件)是一个有向无环图
-
AOE网(用顶点表示事件,用有向边表示活动)
-
拓扑排序
结构体
#define MaxVertexNum 100 typedef struct ArcNode{ //边表结点 int adjvex; //该弧所指向的顶点的位置 struct ArcNode *nextarc; //指向下一条弧的指针 //InfoType info; //网的边权值 }ArcNode; typedef struct VNode{ //顶点表结点 VertexType data; //顶点的信息 ArcNode*firstarc; //指向第一条依附该顶点的弧的指针 }VNode,AdjList[MaxVertexNum]; typedef struct{ AdjList vertices; //邻接表 int vexnum,arcnum; //图的顶点数和弧数 }Graph; //Graph是以邻接表存储的图类型
新定义:
bool TopologicalSort(Graph G){ InitStack(S); //初始化栈,存储入度为0的顶点 for(int i=0;i<G.vexnum;i++) if(indegree[i]==0) Push(S,i); //将所有的入度为0的顶点进栈 int count=0; //计数,记录当前已经输出的顶点数 while(!IsEmpty(S)){ Pop(S,i); //栈顶元素出栈 print[count++]=i; //输出顶点i for(p=G.vertices[i].firstarc;p;p=p->nextarc){ //将所有i指向的顶点的入度减1,并且将入度减为0的顶点压入栈S v=p->adjvex; if(!(--indegree[v])) Push(S,v); //入度为0,则入栈 } } //while if(count<G.vexnum) return false; //排序失败,有向图中有回路 else return true; //拓扑排序成功 }
-
逆拓扑排序(深度优先遍历)
void DFSTraverse(Graph G){ //对图G进行深度优先遍历 for( v=0;v<G.vexnum;++v) visited[v]=FALSE; //初始化已访问标记数据 for(v=o;v<G.vexnum'++v) //本代码中是从V=0开始遍历 if(!visited[v]) DFS[G,v]; } void DFS(Graph G,int V){ //从顶点v出发,深度优先遍历图G // visited(v); //访问顶点V visited[v]=TRUE; //设已访问标记 for(w=FirstNeighbor(G,v);W>=0;W=NextNeighbor(G,v,w)) if(!visited[w]){ //w为u的尚未访问的邻接顶点 DFS(G,w); } print(v); //输出顶点 (通过调用栈来进行的输出) }
邻接表时间复杂度:O(V+E) 邻接矩阵:O(v^2)
-
求关键路径的步骤