【数据结构C语言】深度优先遍历DFS检查无向图和有向图回路

【待更新...】

对天勤数据结构课后习题的深度思考:

问题:T218 1.(2) 

解答:T226 

1)有向图 在DFS的visited[]数组0,1状态上进行扩充,0表示为访问过,1表示已访问但还没监测完这个顶点可能出现的回路(即还没退出系统栈,处于有子结点还在访问的状态),2表示该结点已经退出系统栈(即不在递归层中)。进入DFS函数对v访问时,标记为1,然后访问子结点,如果子结点被访问过了,且子结点访问状态为1则表示有回路,如果子结点状态为2,则过滤掉这个结点。在即将退出递归层时,将结点标记为2,然后退出系统栈,返回上一层。 

2)无向图 存在双向边的情况

1.对于无向图

如果在DFS过程中检查到回边存在两种情况:

1)存在环

2)存在双向边。此时要过滤掉双向边。在DFS函数外部设置变量i,编号数组no[N],并初始化为0。进入DFS时,i++(表示来到了一个新的双亲结点),访问某个顶点a,给它编号i,然后访问孩子结点b,如果孩子结点b未访问过,则在DFS递归之前将b的编号设置为i+1。如果访问过程中来到一个结点c,它的孩子结点d已经被访问过,且d的编号+1等于c的编号,证明为双向边,否则为回路。退出一层DFS函数时,i--,表示回到了双亲结点。

核心代码:

int i = -1;
int no[maxSize] = { 0 };
int visit[maxSize] = { 0 };

void DFS(AGraph* G, int v)
{
	++i;
	ArcNode* p;
	int j;
	printf("%c ", G->adjlist[v].data);
	visit[v] = 1;
	no[v] = i;
	p = G->adjlist[v].firstarc;

	while (p != NULL)
	{
		j = p->adjvex;
		if (visit[j] == 0)
		{
			no[j] = i + 1;
			DFS(G, j);
		}
		else if (no[v] != (no[j] + 1))
		{
			printf("存在回路"); 
		}
		p = p->nextarc;
	}
	--i;
}

完整代码:

#include 
#include 
#define maxSize 100

typedef struct ArcNode
{
	int adjvex;
	struct ArcNode* nextarc;
}ArcNode;

typedef struct
{
	char data;
	ArcNode* firstarc;
}VNode;

typedef struct
{
	VNode adjlist[maxSize];
	int n, e;//顶点个数和边数
}AGraph;

FILE* fp;
void InsertEdge(AGraph* G, int v1, int v2)
{
	ArcNode* p = (ArcNode*)malloc(sizeof(ArcNode));
	p->adjvex = v2;
	p->nextarc = G->adjlist[v1].firstarc;
	G->adjlist[v1].firstarc = p;

	/*无向图再加入下面一段代码*/
	p = (ArcNode*)malloc(sizeof(ArcNode));//不可将p置空,因为要再新插入一个结点,必须给这个结点开辟一个空间
	p->adjvex = v1;
	p->nextarc = G->adjlist[v2].firstarc;
	G->adjlist[v2].firstarc = p;

}


void CreateGraph(AGraph* G)
{
	int nv, ne, i, v1, v2;
	fp = fopen("C:\\CodeBlocksProject\\AG.txt", "r");
	fscanf(fp,"%d%d", &nv, &ne);
	for (i = 0; i < nv; i++)
	{
		G->adjlist[i].firstarc = NULL;
		fscanf(fp, "%c", &G->adjlist[i].data);
	}

	for (i = 0; i < ne; ++i)
	{
		fscanf(fp, "%d%d", &v1, &v2);
		InsertEdge(G, v1, v2);
	}
	G->e = ne;
	G->n = nv;
	fclose(fp);
}
int i = -1;
int no[maxSize] = { 0 };
int visit[maxSize] = { 0 };

void DFS(AGraph* G, int v)
{
	++i;
	ArcNode* p;
	int j;
	printf("%c ", G->adjlist[v].data);
	visit[v] = 1;
	no[v] = i;
	p = G->adjlist[v].firstarc;

	while (p != NULL)
	{
		j = p->adjvex;
		if (visit[j] == 0)
		{
			no[j] = i + 1;
			DFS(G, j);
		}
		else if (no[v] != (no[j] + 1))
		{
			printf("存在回路"); 
		}
		p = p->nextarc;
	}
	--i;
}

int main()
{
	AGraph G;
	CreateGraph(&G);
	DFS(&G, 0);

	return 0;
}

输入的示例:

5 5ABCDE
0 1
0 2
0 3
3 2
3 4
 

你可能感兴趣的:(初试数据结构学习)