打算在最近花点时间学习线性代数,因为线代快要结课了但是学的还不太明白。
今天主要复习了一下拓扑排序:
-
拓扑排序就是一个有向无环图(DAG)的所有顶点的线性排序。只有有向无环图才有拓扑排序,不是有向无环图没有拓扑排序这一说。
-
如图:
-
实现拓扑排序:
-
从一个有向无环图中选择一个入度为0的顶点并输出。
-
从这个图中删除这个顶点和所有以它为起点的有向边。
-
重复上面的步骤直到当前的有向无环图为空或当前图中不存在入度为0的顶点为止。如果出现的是后面那种情况则说明这个图中必然存在环。
4.例如:
拓扑排序后的结果为:1,2,3,4,5。
一个有向无环图可以拥有一个或者多个拓扑排序。
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define MAXVEX 10
typedef char VerType; //顶点值类型
struct EdgeNode{
int adjvex; //邻接点域,存储该顶点对应的下标
int weight; //用于存储权值,对于非网图可以不需要
EdgeNode* next; //下一个结点
};
struct VertexNode{
int in; //入度
VerType data; //值
EdgeNode* firstedge; //邻接表头指针
};
struct Graph{
VertexNode vers[MAXVEX];
int numVertexes, numEdges; //顶点数和边数
};
/* 拓扑排序,若G没有回路,则输出拓扑排序序列并返回OK,若有回路返回ERROR */
bool TopologicalSort(Graph* G){
EdgeNode* e;
int i, k, gettop;
int top = 0; //栈指针下标
int count = 0; //统计输出顶点个数
int* stack; //存储入度为0的顶点
stack = (int*)malloc(G->numVertexes * sizeof(int));
for(i = 0;i<G->numVertexes;i++) //遍历所有结点
if(G->vers[i].in == 0)
stack[++top] = i; //将入度为0的顶点入栈
while(top != 0){
gettop = stack[top--]; //出栈
printf("%c ",G->vers[gettop].data);
count++; //统计输出顶点数
for(e=G->vers[gettop].firstedge; e; e = e->next){
//弧表遍历
k = e->adjvex;
if(!(--G->vers[k].in)) //将k号顶点邻接点的入度减1
stack[++top] = k; //若为0则入栈,以便下次循环输出
}
}
if(count < G->numVertexes) //如果count小于顶点数,说明存在环
return false;
else
return true;
}
/* 图初始化 */
void CreateGraph(Graph* G){
int i, m, n;
printf("输入顶点数和边数:\n");
scanf("%d,%d",&G->numVertexes, &G->numEdges);
printf("输入顶点值:\n");
for(i=0;i<G->numVertexes;i++){
getchar(); //吃掉回车
scanf("%c",&G->vers[i].data);
}
//初始化图头结点指针和入度值
for(i=0;i<G->numVertexes;i++){
G->vers[i].firstedge = NULL;
G->vers[i].in = 0; //入度为0
}
printf("输入边:\n");
for(i=0;i<G->numEdges;i++){
scanf("%d,%d",&m, &n);
EdgeNode* newNode = (EdgeNode*)malloc(sizeof(EdgeNode));
newNode->next = G->vers[m].firstedge == NULL ? NULL : G->vers[m].firstedge;
newNode->adjvex = n;
G->vers[m].firstedge = newNode;
G->vers[n].in++; //入度+1
}
}
int main(){
Graph* G = (Graph*)malloc(sizeof(Graph));
CreateGraph(G);
if(TopologicalSort(G)){
printf("拓扑排序完成!\n");
}else{
printf("图存在环");
}
return 0;
}