[深度优先遍历—栈实现]求图中两点是否连通

#include "stdio.h"
//深度优先遍历算法
//求图中起点s到终点e的路径是否存在。图中的每个点至多有2个发出点。图以有向边(0,1)的形式给出. 图中不存在环。
//输入数据
//1 16(casenumber和边的数目)
//0 1 0 2 1 4 1 3 4 8 4 3 2 9 2 5 5 6 5 7 7 99 7 9 9 8 9 10 6 10 3 7 (16条边的数据)
#define MAX 100
typedef struct elem
{
	int ent; //入栈的数据
	int dir; //点的下一个查找方向,0为第一个查找方向,1为第二个,2,3依次类推
}elem;

//栈的定义
elem stack[MAX];
int top;

void initStack()
{
	int i;
	top = -1;
	for(i=0; i<MAX; i++)
	{
		stack[i].ent=-1;
		stack[i].dir=-1;
	}
}
int isFull()
{
	if(top==MAX-1)
	{
		return 1;
	}
	return 0;
}

int isEmpty()
{
	if(top==-1)
	{
		return 1;
	}
	return 0;
}

int push(elem e)
{
	if(isFull() == 1)
	{
		return 0;
	}
	top++;
	stack[top]=e;
	return 1;
}

int pop(elem *e)
{
	if(isEmpty()==1)
	{
		return 0;
	}
	*e=stack[top];
	top--;
	return 1;
}

int getTop(elem * e)
{
	if(isEmpty()==1)
	{
		return 0;
	}
	*e=stack[top];
	return 1;
}

int main()
{
	int tc;
    int edgenum;
	int i,j;
	int DT[MAX][2]; //保存方向边,行号是点的编号,且每个点至多发出2条边。
	int casen;
	int m,n;
	//int flag=0;
	int tmp;
	int s,e;
	int searched[MAX]; //点是否查找过
	elem node;
	elem node2;

	freopen("input.txt", "r", stdin);  //xxl

	for(tc=1; tc<=1/*xxl*/; tc++)
	{
		initStack();

		scanf("%d", &casen);
		scanf("%d", &edgenum);

		for(i=0;i<MAX; i++)  //init
		{
			for(j=0;j<2; j++)
			{
				DT[i][j] = -1;  //init
			}
			searched[i]=0;  //init
		}
	
		for(i=0; i<edgenum; i++) //get data
		{
			scanf("%d", &m);
			scanf("%d", &n);
			if(DT[m][0] == -1)
			{
				DT[m][0]=n;
			}
			else
			{
				DT[m][1]=n;
			}
		}
		
		//DFS search
		s=0;
		e=99;

		//1. 起点入栈
		node.ent=s;
		node.dir= 0;  //0表示下一个查找方向是这个点发出第0条边
		push(node);
		searched[s]=1;

		//2.栈不空
		while(isEmpty()==0)
		{
			//2.1 取栈顶
			getTop(&node2);
			tmp=node2.ent;
			
			if(tmp==e)//2.2 栈顶为出口,此时栈中保存的就是路径
			{
#if 0 //打印路径
				for(i=0;i<=top; i++)
				{
					printf("%d ",stack[i].ent);
				}
				printf("\n");
#endif
				pop(&node2);  //点出栈。不退出循环是为了找所有的可能路径。
				searched[node2.ent]=0;  //去除查找标记,以便其他路径使用该点
			}
			else  //2.3 不为栈顶,则见下一个点push 进站
			{
				if(node2.dir == 0) //first. 先看将first方向的点入栈
				{
					stack[top].dir=1; //在将first点入栈前,先修改当前点的方向值为下一次的方向
					if(DT[tmp][0]!=-1 && searched[DT[tmp][0]] == 0)  //如果下一个点且该点没有查找过
					{
						node.ent=DT[tmp][0];
						node.dir=0; //init dir
						push(node); //入栈
						searched[DT[tmp][0]] = 1; //标记查找过
					}
				}
				else if(node2.dir == 1) //second.否则再将second方向的点入栈
				{
					stack[top].dir=2; //next direction for current node
					if(DT[tmp][1]!=-1 && searched[DT[tmp][1]] == 0) 
					{
						node.ent=DT[tmp][1];
						node.dir=0; //init dir
						push(node);
						searched[DT[tmp][1]] = 1;
					}
				}
				else //如果dir >=2, 表示当前点的所有方向已经查找完
				{
					pop(&node2);  //点出栈
					searched[node2.ent]=0;  ///去除查找标记,以便其他路径使用该点
				}
			}
		}
		
		//printf("#%d %d\n", casen, flag);

	}
	return 0;

}
点赞