C语言实现判别有向图(采用邻接表为存储结构)中是否存在有向环,当有向环存在时,输出构成环的顶点

一、源码

思路及其详细解释看另一篇:关于图的第二题

#include
#include

//定义图的结构体
#define MaxVexNum 100
typedef struct ArcNode{//边表结点
	int data;
	struct ArcNode *next;
}ArcNode;
typedef struct VNode{//顶点表结点
	int data,indegree,outdegree;//indegree、outdegree分别是该顶点的入度和出度,data为顶点号
	struct ArcNode *first;
	bool visited;//访问标记
}VNode;
typedef struct Graph{
	VNode adjlist[MaxVexNum];
	int vexnum,arcnum;
}Graph;

//定义栈的结构体以及相关操作
typedef struct{
	VNode data[MaxVexNum];
	int top;
}Stack;
void InitStack(Stack &s){
	s.top = -1;
}
bool StackEmpty(Stack s){//判栈空
	if(s.top == -1){
		return true;
	}else{
		return false;
	}
}

bool Push(Stack &s,VNode x){//进栈
	if(s.top == MaxVexNum-1){
		return false;
	}else{
		s.data[++s.top] = x;
		return true;
	}
}

VNode Pop(Stack &s){//出栈
	return s.data[s.top--];
	
}


int location(Graph *G,int data){//定位顶点号为data在adjlist中的下标
	int i;
	for(i = 0;i<G->vexnum;i++){
		if(G->adjlist[i].data == data){
			return i;
		}
	}
	return -1;
}

Graph *creat_Graph(){//创建一个图
	int i,j,start;
	Graph *G = (Graph *)malloc(sizeof(Graph));
	ArcNode *p;
	printf("请输入图的顶点数:");
	scanf("%d",&G->vexnum);
	for(i = 0;i<G->vexnum;i++){
		G->adjlist[i].first = NULL;
	}
	printf("请输入图的边数:");
	scanf("%d",&G->arcnum);
	for(i = 0;i<G->vexnum;i++){
		printf("请输入第%d个顶点:",i+1);
		scanf("%d",&G->adjlist[i].data);
	}
	for(i = 0;i<G->arcnum;i++){
		printf("输入边的起点:");
		scanf("%d",&start);
		for(j = 0;j<G->vexnum;j++){
			if(G->adjlist[j].data == start){
				p = (ArcNode *)malloc(sizeof(ArcNode));
				p->next = NULL;
				printf("输入边的终点:");
				scanf("%d",&p->data);
				p->next = G->adjlist[j].first;
				G->adjlist[j].first = p;
			}
		}
	}
	return G;
}

void FindInDegree(Graph *G){  //计算每个顶点的入度
         int i;
         ArcNode *p;
         for (i=0;i<G->vexnum;i++)
               G->adjlist[i].indegree=0;//初始化入度
         for (i=0;i<G->vexnum;i++)
         {
             p=G->adjlist[i].first;
             while(p){
				 G->adjlist[location(G,p->data)].indegree++;
				 p=p->next;
             }
         }
}

void FindOutDegree(Graph *G){  //计算每个顶点的出度                                
         int i ;
         ArcNode *p;
         for (i=0;i<G->vexnum;i++)
               G->adjlist[i].outdegree=0;//初始化出度
         for (i=0;i<G->vexnum;i++)
         {
             p=G->adjlist[i].first;
             while(p){
                   G->adjlist[i].outdegree++;
                   p=p->next;
             }
         }
}

void main(){
	int i,count = 0,j;//count记录被标记的顶点个数
	Stack s;
	VNode v;
	ArcNode *q;
	Graph *G = creat_Graph();
	for(i = 0;i<G->vexnum;i++){//标记的初始化
		G->adjlist[i].visited = false;
	}
	InitStack(s);//栈的初始化
	FindInDegree(G);
	FindOutDegree(G);
	for(i = 0;i<G->vexnum;i++){//将出度或入度为0的顶点入栈并标记
		if(G->adjlist[i].outdegree == 0||G->adjlist[i].indegree == 0){
			Push(s,G->adjlist[i]);
			G->adjlist[i].visited = true;
		}
	}
	while(!StackEmpty(s)){
		v = Pop(s);
		count++;
		for(q = v.first;q;q = q->next){//计算入度的变化
	 		G->adjlist[location(G,q->data)].indegree--;
	 	}
	 	for(j = 0;j<G->vexnum;j++){//计算出度的变化就要对整个图的邻接表进行遍历了
	 		for(q = G->adjlist[j].first;q;q = q->next){
	 			if(q->data == v.data){
	 				G->adjlist[j].outdegree--;
	 			}
	 		}
	 	}
		for(i = 0;i<G->vexnum;i++){//将出度或入度为0 且未被标记(即没有入过栈的)的顶点入栈
			if((G->adjlist[i].outdegree == 0||G->adjlist[i].indegree == 0)&&G->adjlist[i].visited == false){
				Push(s,G->adjlist[i]);
				G->adjlist[i].visited = true;
			}
		}
	}
	if(count<G->vexnum){
		printf("存在环\n");
		printf("构成环的顶点为:");
		for(i = 0;i<G->vexnum;i++){
			if(G->adjlist[i].visited == false){
				printf("%5d",G->adjlist[i].data);
			}
		}
		printf("\n");
	}else{
		printf("不存在环\n");
	}
}

二、演示效果

1、图一及其结果
C语言实现判别有向图(采用邻接表为存储结构)中是否存在有向环,当有向环存在时,输出构成环的顶点_第1张图片
C语言实现判别有向图(采用邻接表为存储结构)中是否存在有向环,当有向环存在时,输出构成环的顶点_第2张图片

2、图二及其结果
C语言实现判别有向图(采用邻接表为存储结构)中是否存在有向环,当有向环存在时,输出构成环的顶点_第3张图片
C语言实现判别有向图(采用邻接表为存储结构)中是否存在有向环,当有向环存在时,输出构成环的顶点_第4张图片

你可能感兴趣的:(数据结构,数据结构,有向图)