拓扑排序手工来算太简单了,写的时候还真遇到了不少困难。
基本思路就是不断遍历结点序列,输出入度为0的结点并将其后继的入度减1,直到所有结点输出完毕。
如果有多个入度为0的结点,从小到大输出用队列可以实现。
#include<stdio.h> #include<string.h> #include<ctype.h> int main() { int n; char str[100]; while(scanf("%d",&n) != EOF) { int degree[n]; // 入度 int next[n][n]; // 后继矩阵 int queue[n]; // 队列 int front = 0,rear = 0; // 队头 队尾 for(int i = 0;i<n;i++) // 初始化 { degree[i] = 0; queue[i] = -1; for(int j = 0;j<n;j++) next[i][j] = -1; } for(int j = 0;j<n;j++) { int flag = 0; // flag为1表示在读后继 scanf("%s",str); for(int i = 0;i<strlen(str);i++) { int temp; if(isdigit(str[i])) // 只读数字,Task及其它直接跳过 { if(flag) // 在读括号里的后缀时 { degree[str[i] - '0']++; // 入度加1 next[temp][str[i]-'0'] = 1; // 更新后继 } else // 读括号前的结点 temp = str[i] - '0'; } else if(str[i] == '(') // 开始读后继 flag = 1; } } int cnt = 0; for(int i = 0;i<n;i++) // 将入度为0的结点入队 if(!degree[i]) queue[rear++] = i; while(1) { if(cnt != n -1) // 非最后的结点 { int temp = queue[front++]; // 从队头出队一个元素 printf("Task%d ",temp); for(int i = 0;i<n;i++) // 将后继的所有节点入度减1 { if(next[temp][i] != -1) { degree[i] --; if(!degree[i]) // 如果入度减到0则入队 queue[rear++] = i; } } cnt++; } else // 最后一个元素 { printf("Task%d\n",queue[front]); break; } } } return 0; }