拓扑排序步骤: 》在有向图中选一个没有前驱的顶点(入度为0)且输出。 》从图中删除该顶点和以它为尾的弧。 重复上述两步。 》直至全部顶点均已输出。 》当前图中不存在无前驱的顶点则说明有向图中存在环。
#include <stack> #include <memory> #include <iostream> #include <queue> #include <cstring> #include <cstdio> using namespace std; #define MAX 1000//定义图结点的最大个数 int n, m; //n代表顶点数,m代表边数 typedef struct arc_data //边信息 { int vex; //邻接的结点在数组中的编号 struct arc_data *next; } arc_data; struct Node //顶点信息 { arc_data *head; } adj[MAX]; bool v[MAX]= {false}; int in_count[MAX]; //记录结点入度数的数组 void create( ) //生成图(邻接表实现) { int i; memset(in_count, 0, sizeof(int)*(n+1)); //入度数组清零 for(i=1; i<=n; ++i) //初始化表头结点 adj[i].head = NULL; for(i=0; i<m; i++) { int a, b; scanf("%d%d", &a, &b); in_count[b]++; // 记录入度值 arc_data *q; q = new arc_data; q->vex = b; q->next= adj[a].head; //新边插入邻接表~~ adj[a].head = q; } } void topo_sort() //邻接表拓扑排序 { stack<int> S; arc_data *p ; int showNum=0; //记录输出的结点的数目 for(int i=1; i<=n; ++i)//在in_count数组中找出入度为0的结点,并分别入栈 if(in_count[i]==0) S.push(i); //入度为0的全入栈 while(!S.empty()) { int v=S.top(); S.pop(); printf(" %d", v); in_count[v]=-1; //将该点入度调为-1 ++showNum; p=adj[v].head; while(p!=NULL) //遍历以v为起点所临接的点 { //结点入度数减1 --in_count[p->vex]; if(in_count[p->vex]==0) //入度数为0时入栈 S.push(p->vex); p=p->next; } } puts(""); if(showNum<n) printf("该图中含有有向环!\n"); } void dfs(int i) //邻接表DFS { printf(" %d", i); v[i]=true; arc_data *p = adj[i].head; while(p!=NULL) { if(!v[p->vex]) { dfs(p->vex); } p = p->next; } } void bfs(int i) //邻接表BFS { queue<int> Q; Q.push(i); v[i]=true; while(!Q.empty()) { int j=Q.front(); Q.pop(); printf(" %d", j); arc_data *p = adj[j].head; while(p!=NULL) { if(!v[p->vex]) { Q.push(p->vex); v[p->vex]=true; } p = p->next; } } } int main() { while(scanf("%d%d", &n, &m)!=EOF) { create(); printf("拓扑排序: "); topo_sort(); printf("DFS: "); memset(v, 0, sizeof(v)); for(int i=1; i<=n; i++) //确保每个顶点都搜一遍 if(!v[i]) dfs(i); puts(""); printf("BFS: "); memset(v, 0, sizeof(v)); for(int i=1; i<=n; i++) if(!v[i]) bfs(i); puts(""); } return 0; }