图--判断是否有环

17 篇文章 0 订阅
14 篇文章 0 订阅

 (1)拓扑排序

#include <iostream>
#include <stack>
using namespace std;
//
//  aov.h
//  aov
//
//  Created by 吴珝君 on 2018/12/25.
//  Copyright  ©   2018年 闲着也是贤者. All rights reserved.
//
/************************************************************************/
/* 活动在顶点上的网(Activity On Vertex network ,AOV):反映工程活动的先后顺序
AOV是以顶点表示活动,用边来表示活动先后顺序并且没有回路的有向图。因为AOV网具有实际
意义,所以有回路就代表一项活动以自己为前提,这显然违背实际
*/
/************************************************************************/
//图的存储--邻接表
#define  MAXSIZE 100
#define  INF 65535
typedef struct ArcNode
{
	int adjvex;//该边所指向的结点的位置‘
	struct ArcNode *nextarc;
	int info;//如权值信息
	
};
typedef struct 
{
	char data;
	int count ;//此句为新增部分,count来统计顶点当前的入度
	ArcNode *firstNode;
	
}VNode;
typedef struct 
{
	VNode adjlist[MAXSIZE];
	int n,e;//顶点数和边数
}AGraph;
//创建图
/************************************************************************/
/* 算法思想:
	1)从有向图中选择一个没有入度的顶点输出
	2)删除1)中的顶点,并且删除从该顶点发出的所有边
	3)重复以上步骤,直到剩余的图中不存在没有入度的顶点为止
*/
/************************************************************************/
int topSort(AGraph *g)
{
	int  n=0;
	stack<int> s;
	ArcNode *p;
	/************************************************************************/
	/*这个循环将图中入度为0的顶点入栈                                         */
	/************************************************************************/
	for (int i =0;i<g->n;i++)
	{
		if (g->adjlist[i].count ==0)
		{
			s.push(i);
		}
	}
	/************************************************************************/
	/* 关键操作开始                                                          */ 
	/************************************************************************/
	while(!s.empty())
	{
		int i = s.top();
		++n;//计数器加一,统计当前顶点
		cout<<i<<" ";

		p = g->adjlist[i].firstNode;
		s.pop();
	/************************************************************************/
	/* 这个循环实现了将所有由此顶点引出的边,所指向的顶点的入度减少1,并将这个过程
	中入度变为0的顶点入栈*/
	/************************************************************************/
		while(p!=NULL)
		{
			int j = p->adjvex;//顶点信息
			--(g->adjlist[j].count);
			if (g->adjlist[j].count==0)
			{
				s.push(j);
			}
			p = p->nextarc;
		}
	}
	if (n ==g->n)
	{
		return 1;
	}
	else
		return 0; 
}


 int main()
{
	
	
	system("pause");
	return 0;
}

 (2)深度优先遍历

#include <iostream>
#include <stack>
using namespace std;
//
//  dfs.h
//  dfs
//
//  Created by 吴珝君 on 2018/12/25.
//  Copyright  ©   2018年 闲着也是贤者. All rights reserved.
//
/************************************************************************/
/* 活动在顶点上的网(Activity On Vertex network ,AOV):反映工程活动的先后顺序
AOV是以顶点表示活动,用边来表示活动先后顺序并且没有回路的有向图。因为AOV网具有实际
意义,所以有回路就代表一项活动以自己为前提,这显然违背实际
*/
/************************************************************************/
//图的存储--邻接表
#define  MAXSIZE 100
#define  INF 65535
//创建图。
//图的存储--邻接矩阵
#define  MAXSIZE 100
#define  INF 65535
typedef struct 
{
	int  edges[MAXSIZE][MAXSIZE];//存放边的关系的数组
	int  n,e;//n是顶点个数 e是边的个数
	char vex[MAXSIZE];//存放顶点信息
}MGrap;

void createGrap(MGrap *g)
{

	cout <<"请输入顶点数和边的数"<<endl;
	cin>>g->n>>g->e;
	cout<<"请输入顶点信息"<<endl;
	for (int i =0;i<g->n;i++)
	{
		cin>>g->vex[i];
	}
	//初始化矩阵
	for (int i =0;i<g->n;i++)
	{
		for (int j =0;j<g->n;j++)
		{
			g->edges[i][j] = 65535;
		}
	}
	cout<<"请输入边的信息:起始边和终止边 以及值"<<endl;
	for (int i =0;i<g->e;i++)
	{
		int start, end,value;
		cin>>start>>end;
		g->edges[start][end] = 1;
		g->edges[end][start] = 1;
	}
}

//深度优先遍历找出无向图中的环
/************************************************************************/
/*
算法思想:进行深度优先遍历的时候,当考察的点的下一个邻接点是已经被遍历的点,并且
不是自己之前的父节点的时候,我们就找到了一条逆向边,因此可以判断无向图中存在环路
我们使用visited数组记录节点的访问状态,visited[i]=0表示节点i尚未被访问符;visited[i]
=1表示节点i被访问了,但是尚没有被检测完毕;visited[i]= 2表示的是i已经被检测完了,对于
检测完毕的节点,其所有的邻边都已经被考虑过了,如果存在逆向边的话已经被检测了,从而
避免了重复的进行检测,father[i]表示到达节点i经过的前驱节点,通过反向索引father数组
就可以找出这个环。
*/
/************************************************************************/
//本无向图采用邻接矩阵存储。
int visited[MAXSIZE] ={0};
int father[MAXSIZE] = {0};
void DfsWithRecursion(MGrap *g,int v)
{
	visited[v] = 1;
	for (int i =0;i<g->n;i++)
	{
		if (g->edges[v][i]==1&&visited[i]==0)
		{
			father[i] = v;//记录i的前驱(父亲)节点
			DfsWithRecursion(g,i);
		}
		else if (visited[i]==1&&i!=father[v])//如果这个节点已经被访问过了//并且这个节点不是当前节点的父节点 说明遇到环了。
		{
			//打印环
			int t = v;
			cout<<"当前的环是:";
			while(t!=i)
			{
				cout<<t;
				t = father[t];
			}
			cout<<t<<endl;
		}
	}
	
	visited[v] =2;//避免重复统计环的个数


}
 int main()
{

	
	system("pause");
	return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值