图 - 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)
-
求关键路径的步骤
