#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
//使用卡恩算法(Kahn)和深度优先算法(DFS)实现
//拓扑排序和逆拓扑排序
//拓扑排序和逆拓扑排序顶点顺序相反
//图,邻接矩阵存储
#define MaxVertexNum 100 //最大顶点数
typedef struct {
int vex[MaxVertexNum]; //顶点表
int edge[MaxVertexNum][MaxVertexNum]; //边表
int vernum, arcnum; //记录当前图的顶点数量和边数
} MGraph;
int vexIndex(MGraph G, int x);
void visit(int i);
//初始化图
MGraph InitMgraph() {
MGraph graph;
memset(graph.edge, 0, sizeof(graph.edge));
graph.arcnum = 0;
graph.vernum = 0;
return graph;
}
//带头节点
//链队列节点
typedef struct Linknode {
int data;
struct Linknode *next;
} Linknode;
//链队列
typedef struct {
//队头指针
Linknode *front;
//队尾指针
Linknode *rear;
} LinkQueue;
//初始化队列
void InitQueue(LinkQueue *Q) {
//创建头结点
Linknode *temp = (Linknode *) malloc(sizeof(Linknode));
Q->front = temp;
Q->rear = temp;
}
//入队
void EnQueue(LinkQueue *Q, int data) {
//创造节点
Linknode *temp = (Linknode *) malloc(sizeof(Linknode));
//赋值
temp->data = data;
temp->next = NULL;
//连接插入节点
Q->rear->next = temp;
//队尾指针更换
Q->rear = temp;
}
//出队
bool DeQueue(LinkQueue *Q, int *e) {
//队列为空
if (Q->rear == Q->front) {
return false;
}
//要出队的节点
Linknode *temp = Q->front->next;
*e = temp->data;
//队头指针更换
Q->front->next = temp->next;
free(temp);
//最后一个节点出队
if (temp == Q->rear) {
//队尾指针更换
Q->rear = Q->front;
}
return true;
}
/
//借助队列实现拓扑排序
//卡恩算法
bool TopologicalSort(MGraph G) {
//初始化队列
LinkQueue *linkQueue = (Linknode *) malloc(sizeof(linkQueue));
InitQueue(linkQueue);
//当前顶点的入度
int indegree[G.vernum];
//记录拓扑排序
int print[G.vernum];
memset(indegree, 0, sizeof(indegree));
//初始化入度数组
for (int i = 0; i < G.vernum; ++i) {
for (int j = 0; j < G.vernum; j++) {
if (G.edge[j][i] == 1) {
indegree[i]++;
}
}
}
//初始化print数组
memset(print, -1, sizeof(print));
//度为0的顶点索引入队列
for (int i = 0; i < G.vernum; i++) {
if (indegree[i] == 0) {
EnQueue(linkQueue, i);
indegree[i] = -1;
}
}
//记录顶点个数
int count = 0;
int *e = malloc(sizeof(int));
while (linkQueue->rear != linkQueue->front) {
DeQueue(linkQueue, e);
print[count] = G.vex[*e];
count++;
for (int i = 0; i < G.vernum; ++i) {
if (G.edge[*e][i] == 1) {
indegree[i]--;
}
if (indegree[i] == 0) {
EnQueue(linkQueue, i);
indegree[i] = -1;
}
}
}
if (count < G.vernum)
return false;
else {
for (int i = 0; i < G.vernum; i++) {
printf("%d ", print[i]);
}
return true;
}
}
int time;
int finalTime[100];
int visited[100];
//DFS算法实现拓扑排序
//v为入度为0的顶点
void DFSTopologicalSort(MGraph G, int i) {
//对i做已访问标记
visited[vexIndex(G, i)] = 1;
//找到i的所有邻接点
for (int j = 0; j < G.vernum; j++) {
if (visited[j] == 0 && G.edge[vexIndex(G, i)][j] == 1) {
DFSTopologicalSort(G, G.vex[j]);
}
}
(time)++;
finalTime[vexIndex(G, i)] = time;
}
//使用后visited会被重新赋值,需重置
//建议用一个变量临时保存原有图
void DFSTraverseTopologicalSort(MGraph G, int i) {
time = 0;
for (int j = 0; j < G.vernum; j++) {
visited[j] = 0;
}
DFSTopologicalSort(G, i);
for (int j = 0; j < G.vernum; j++) {
if (visited[j] == 0) {
DFSTopologicalSort(G, G.vex[j]);
}
}
for (int j = 0; j < G.vernum; j++) {
printf("%d ", finalTime[j]);
}
}
//有向图深度优先搜索
void niDFSTopologicalSort(MGraph G, int i) {
//对i做已访问标记
visited[vexIndex(G, i)] = 1;
//找到i的所有邻接点
for (int j = 0; j < G.vernum; j++) {
if (visited[j] == 0 && G.edge[vexIndex(G, i)][j] == 1) {
niDFSTopologicalSort(G, G.vex[j]);
}
}
printf("%d ", i);
}
//使用后visited会被重新赋值,需重置
//建议用一个变量临时保存原有图
//连通图和非连通图的深度优先搜索(改进)
void niDFSTraverseTopologicalSort(MGraph G, int i) {
for (int j = 0; j < G.vernum; j++) {
visited[j] = 0;
}
niDFSTopologicalSort(G, i);
for (int j = 0; j < G.vernum; j++) {
if (visited[j] == 0) {
niDFSTopologicalSort(G, G.vex[j]);
}
}
}
int main(void) {
//有向图
//初始化图
MGraph graph = InitMgraph();
//图添加元素
//顶点集添加1,2,3,4,5
for (int i = 0; i < 5; i++) {
graph.vex[i] = i + 1;
graph.vernum++;
}
//边集加边<1,2>,<1,4>,<2,3>,<2,4>,<3,5>,<4,3>,<4,5>
graph.edge[0][1] = 1;
graph.edge[0][3] = 1;
graph.edge[1][2] = 1;
graph.edge[1][3] = 1;
graph.edge[2][4] = 1;
graph.edge[3][2] = 1;
graph.edge[3][4] = 1;
graph.arcnum = 7;
printf("拓扑排序序列:\n");
TopologicalSort(graph);
printf("\n");
printf("tineFinal数组:\n");
DFSTraverseTopologicalSort(graph, 1);
printf("\n");
printf("逆拓扑排序序列:\n");
niDFSTraverseTopologicalSort(graph, 5);
}
//返回x在顶点表的索引
int vexIndex(MGraph G, int x) {
int index = -1;
for (int i = 0; i < G.vernum; i++) {
if (G.vex[i] == x) {
index = i;
break;
}
}
return index;
}
测试用例
