拓扑排序,可以检查图中是否存在环,若图中的顶点都在他的 拓扑排序中,则它不存在环,若有的点不存在拓扑排序序列中,不在序列的结点存在环,或者它在环之中。
//拓扑排序
#include<iostream>
#define max 100
#define maxint 32726
#define maxvex 100
using namespace std ;
typedef struct stack{
char *base;
char *top;
int maxsize;
}Stack;
//定义栈
void initstack(Stack &S){
S.base=new char [max];
if(!S.base){
return ;
}
S.top=S.base;
S.maxsize=max;
}
//入栈
char pushstack(Stack &S ,char e){
if(S.top-S.base==S.maxsize){
printf("栈已满\n");
return 0;
}
*S.top++=e;
}
//出栈
char popstack (Stack &S){
char e;
if(S.top==S.base){
printf("栈已空\n");
return 0;
}
e=*--S.top;
return e;
}
//判断栈空
int emptystack(Stack &S){
if(S.top==S.base)
return 1;
else return 0;
}
//边节点
typedef struct vexnode {
int adjvex;
char v;
struct vexnode *nextarc;
float info;
}ArNode;
typedef struct Vnode { //顶点信息
char data;
ArNode *firstarc; //指向第一个边结点
}Vonde,Adjust[100];
typedef struct {
Adjust survice;//邻接表
int vexnum,acrnum;//图的当前顶点数和边数
}ALgraph;
//邻接表查找UND
int locate1(ALgraph&R, char v,int n){
int j,i;
for(i=1;i<=n;i++){
if(R.survice[i].data==v){
j=i;
}
}
return j;
}
void creatUND(ALgraph &R){
char v1,v2;
int i1,i2;//两个顶点的位置和权值
float i3;
printf("请输入顶点数和边数:");
cin>>R.vexnum>>R.acrnum; //输入顶点数和边数
printf("请输入各个顶点的值:\n");
for(int i=1;i<=R.vexnum;i++){
cin>>R.survice[i].data;//输入各个顶点的信息
R.survice[i].firstarc=NULL;
}
printf("请输入每条边依附的两个结点和权值:\n");
for(int i=1;i<=R.acrnum;i++){
cin>>v1>>v2>>i3;
i1=locate1(R,v1,R.vexnum);
i2=locate1(R,v2,R.vexnum);
ArNode *p1=new ArNode;
p1->adjvex=i1;//记录顶点的位置
p1->info=i3;//记录权值
p1->v=v2;//记录边点的值
p1->nextarc=R.survice[i1].firstarc;
R.survice[i1].firstarc=p1;// 将新节点*p2插入顶点Vi1的邻接表中
}
ArNode *p2;
for(int i=1;i<=R.vexnum;i++){
p2=R.survice[i].firstarc;
while(p2){
printf("<%c , %c> : %.1f ",R.survice[i].data,p2->v,p2->info);
p2=p2->nextarc;
}
printf("\n");
}
}
//拓扑排序
void Toposort(ALgraph &R ,Stack &S){
int degree[R.vexnum+1]={0};//记录各个结点的入度
char topo[R.vexnum];//排序之后存入的数组
ArNode *p;
for(int i=1;i<=R.vexnum;i++){//遍历将各个结点的入度记录在数组中
p=R.survice[i].firstarc;
while(p){
int b=locate1(R,p->v,R.vexnum);
degree[b]++;
p=p->nextarc;
}
}
char s;//入度为零的结点
char m;//出栈元素
int k=0,u;
initstack(S);
for(int i=1;i<=R.vexnum;i++){//将顶点入度为零的点入栈
if(degree[i]==0){
s=R.survice[i].data;
pushstack(S,s);
}
}
ArNode *p1;
//栈非空的情况下进行以下操作
while(!emptystack(S)){
m=popstack(S);//栈顶元素出栈
topo[k]=m;//把输出的元素放到此数组中
k++;//下标进行加加
u=locate1(R,m,R.vexnum);//找到此顶点的下标,让其入度减一
degree[u]--;
p1=R.survice[u].firstarc;//访问它的临结点
while(p1){
degree[locate1(R,p1->v,R.vexnum)]--;//让输出结点的临结点的入度减一
if(degree[locate1(R,p1->v,R.vexnum)]==0){//如果临结点的入度等于零的话,让其进栈
pushstack(S,p1->v);
}
p1=p1->nextarc;
}
/*for(int i=1;i<=R.vexnum;i++){
if(degree[i]==0){
pushstack(S,R.survice[i].data);
}
} */
}
printf("拓扑排序结果为:");
for(int i=0;i<k;i++){
printf("%c " ,topo[i]);
}
printf("\n");
if(k<R.vexnum-1){
printf("该有向图有环\n");
}else{
printf("该有向图没环\n");
}
}
/*
输入顶点数 6 边数 8
各个顶点的值 1 2 3 4 5 6 7 8
分别输入的顶点和权值
1 2 1
1 4 1
1 3 1
3 2 1
3 5 1
4 5 1
6 4 1
6 5 1
*/
int main(){
Stack S;
ALgraph R;
creatUND(R);
Toposort(R ,S);
}