图的应用
//图的应用
//**1.求最小生成树
// (1)Prim算法(时间复杂度O(|V|^2))
// (2)kulusiteer(时间复杂度O(|E|*log2|E|))
//**2.单源最短路径:
// (1)广度优先遍历实现(只能用于无权图)
// (2)Dijkstra算法(可以用于有权图,用于负权值的时候会出问题,时间复杂度O(|V|^2))
//**3.各个顶点之间的最短路径
// (1)Floyd算法(带权图和无权图和负权图都适用,但是无法解决带有负权回路的图,时间复杂度O(|V|^3))
//**4.拓扑排序
//
//广度优先遍历实现
void BFS_MIN_Distance(Graph G,int u){
//d[i]表示从u到i结点的最短路径
for(int i = 0;i<G.vexnum;i++){ //vexnum为结点个数
d[i] = 0; //此处等于无穷
path[i] = -1; //最短路径从那个顶点过来(某个定点的直接前驱)
}
d[u] = 0;
visited[u] = true;
EnQueue(Q,u);
while(!isEmpty(Q)){
DeQueue(Q,u); //队头元素出队
for(w = FitstNeighbor(G,u);w>=0;w = NextNeighbor(G,u,w)){
if(!visited[w]){ //w为u的尚未访问的临界顶点
d[w] = d[u]+1; //路径长度+1
path[w] = u; //最短路径应从u到w
visited[w] = true; //设已访问标记
EnQueue(Q,w); //顶点w入队
}
}
}
}
//Dijkstra算法
//Floyd算法(伪代码)
//准备工作。。。初始化矩阵a和path
void Floyd(Graph G){
for(int k = 0;k<n;k++){
for(int i = 0;i<n;i++){ //遍历矩阵
for(int j = 0;j<n;j++){
if(A[i][j]>A[i][k]+A[k][j]){
A[i][j] = A[i][k]+A[k][j]; //更新路径长度
path[i][j] = k;
}
}
}
}
}
//拓扑排序
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)){ //栈不空,则存在入度为0的顶点
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,则入栈
}
}
}
if(count<<G.vexnum) return false; //排序失败,说明图中有回路
else return true; //排序成功
}
//逆拓扑排序(找到出度为0的顶点)
//用DFS算法实现逆拓扑排序
void DFSTraverse(Graph G){
for(v = 0;v<G.vexnum;v++){
visited[v] = false;
}
for(v = 0;v<G.vexnum;v++){
if(!visited[v]){
DFS(G,v);
}
}
}
void DFS(Graph G,int v){
visited[v] = true;
for(w = FirstNeighbor(G,v);w>=0;w = NextNeighbor(G,v,w)){
if(!visited[w]){
DFS(G,w);
}
}
print(v); //输出逆拓扑排序
}