版权声明:本文为博主原创文章,若有错误之处望大家批评指正!转载需附上原文链接,谢谢! https://blog.csdn.net/summer_dew/article/details/83042121
拓扑排序原理:https://blog.csdn.net/summer_dew/article/details/81604206
【测试数据】
【结果】
【数据结构】邻接表为例
需要将邻接表的数据结构加上一个count,表示入度
typedef struct VNode{
char data;
int count; //入度
ArcNode *firstarc; //第一条边
}VNode, AdjList[MAX_VERTEX_NUM];
【代码】
//计算每个顶点的入度
void CntGraphIndegree(ALGraph *pG) {
ArcNode *p;
int i;
for (i=0; i<pG->vernum; i++) {
for (p=pG->vers[i].firstarc; p; p=p->next) {
pG->vers[p->adjV].count++;
}
}
}
// 拓扑排序,并打印拓扑序列
int TopSort(ALGraph *pG) {
int i,j;
int n=0;
int stack[maxSize],top=-1; //保存当前所有入度为0的顶点
ArcNode *p;
CntGraphIndegree(pG); //计算入度
//将入度为0的顶点压入栈中
for (i=0; i<pG->vernum; i++) {
if (pG->vers[i].count==0)
stack[++top]=i;
}
while (top!=-1) {
i = stack[top--]; //顶点出栈,等效于在图中删掉
++n;
printf("%c ", pG->vers[i].data);
p=pG->vers[i].firstarc;
while (p!=NULL) {
j = p->adjV;
--(pG->vers[j].count);
if (pG->vers[j].count==0)
stack[++top]=j;
p=p->next;
}
}
if (n==pG->vernum) //拓扑排序后没有剩余顶点
return 1;
else //拓扑排序后还有剩余顶点
return 0;
}
【完整代码】
#include<stdio.h>
#include<stdlib.h>
#define maxSize 50
#define MAX_VERTEX_NUM 20
#ifndef BASE
#define BASE
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int Status;
typedef int bool;
#endif
typedef struct ArcNode{
int adjV;
struct ArcNode *next;
}ArcNode;
typedef struct VNode{
char data;
int count; //入度
ArcNode *firstarc; //第一条边
}VNode, AdjList[MAX_VERTEX_NUM];
typedef struct{
int vernum,arcnum;
AdjList vers;
}ALGraph;
/*------------------------
|创建有向图的邻接表 |
------------------------*/
Status InitGraph_AL(ALGraph *pG) { //初始化
int i;
pG->arcnum = 0;
pG->vernum = 0;
for (i=0; i<MAX_VERTEX_NUM; ++i)
pG->vers[i].firstarc = NULL; //VC++6.0中指针初始化为0xcccccccc
return OK;
}
int LocateVex_AL(ALGraph G, char e) { //定位值为e的元素下标
int i;
for (i=0; i<G.vernum; ++i) {
if (G.vers[i].data == e) {
return i;
}
}
return -1;
}
Status CreateDG_AL(ALGraph *pG) { //创建有向图的邻接表--不带权
//输入规则:顶点数目->弧的数目->各顶点的信息->各条弧的信息
int i,a,b;
char tmp[MAX_VERTEX_NUM];
char h,t;
ArcNode *p, *q;
InitGraph_AL(pG); //VC++6.0中指针初始化为0xcccccccc,如果不将指针初始化为NULL,会出错
//顶点数目
scanf("%d", &i); if (i<0) return ERROR;
pG->vernum = i;
//弧的数目
scanf("%d", &i); if (i<0) return ERROR;
pG->arcnum = i;
//各顶点信息
scanf("%s", tmp);
for (i=0; i<pG->vernum; ++i) {
pG->vers[i].data=tmp[i];
pG->vers[i].count=0;
}
//弧的信息
for (i=0; i<pG->arcnum; ++i) {
scanf("%s", tmp);
h = tmp[0]; t = tmp[2];
a = LocateVex_AL(*pG, h);
b = LocateVex_AL(*pG, t);
if (a<0 || b<0) return ERROR;
p = (ArcNode *)malloc(sizeof(ArcNode)); if (!p) exit(OVERFLOW);
p->adjV=b;p->next=NULL;
if (pG->vers[a].firstarc) { //已经有边了
for (q = pG->vers[a].firstarc; q->next; q=q->next) ; //找到最后一条
q->next = p;
} else { //第一条边
pG->vers[a].firstarc = p;
}
}
return OK;
}
//计算每个顶点的入度
void CntGraphIndegree(ALGraph *pG) {
ArcNode *p;
int i;
for (i=0; i<pG->vernum; i++) {
for (p=pG->vers[i].firstarc; p; p=p->next) {
pG->vers[p->adjV].count++;
}
}
}
// 拓扑排序,并打印拓扑序列
int TopSort(ALGraph *pG) {
int i,j;
int n=0;
int stack[maxSize],top=-1; //保存当前所有入度为0的顶点
ArcNode *p;
CntGraphIndegree(pG); //计算入度
//将入度为0的顶点压入栈中
for (i=0; i<pG->vernum; i++) {
if (pG->vers[i].count==0)
stack[++top]=i;
}
while (top!=-1) {
i = stack[top--]; //顶点出栈,等效于在图中删掉
++n;
printf("%c ", pG->vers[i].data);
p=pG->vers[i].firstarc;
while (p!=NULL) {
j = p->adjV;
--(pG->vers[j].count);
if (pG->vers[j].count==0)
stack[++top]=j;
p=p->next;
}
}
if (n==pG->vernum) //拓扑排序后没有剩余顶点
return 1;
else //拓扑排序后还有剩余顶点
return 0;
}
int main() {
/*
测试数据:没有回路
9
11
ABCDEFGHI
A,D
B,D
B,E
C,E
D,F
D,G
E,H
F,I
G,E
G,I
H,I
测试数据二:有回路
9
11
ABCDEFGHI
A,D
B,D
C,E
D,F
D,G
E,B
E,H
F,I
G,E
G,I
H,I
*/
ALGraph G;
int ret;
CreateDG_AL(&G);
ret = TopSort(&G);
printf("\n该有向图是否有回路:%d\n", !ret);
return 0;
}