算法导论-第22章-基本的图算法-22.3 深度优先搜索-22.3-7-使用栈来代替递归实现DFS

题目:

重写过程DFS,利用一个栈来消除递归

代码:

#include 
#include 
using namespace std;

#define N 10
#define WHITE 0
#define GRAY 1
#define BLACK 2

//边结点结构
struct Edge
{
	int start;//有向图的起点
	int end;//有向图的终点
	int type;//边的类型
	Edge *next;//指向同一个起点的下一条边
	Edge(int s, int e):start(s),end(e),next(NULL){}
};
//顶点结点结构
struct Vertex
{
	int id;
	Edge *head;//指向以该点为起点的第一条边
	int color;//顶点的颜色
	Vertex *p;//指向遍历结果的父结点(前驱点)
	int d, f;//第一次被发现的时间和结束检查的时间
	Vertex(int i):head(NULL),color(WHITE),p(NULL),d(0x7fffffff),id(i){}
};
//图结构
struct Graph
{
	Vertex *V[N+1];//N个顶点,V[1]是指向第1个点的链表的指针,V[1]
	Graph()
	{
		int i;
		for(i = 1; i <= N; i++)
			V[i] = new Vertex(i);
	}
	~Graph()
	{
		int i;
		for(i = 1; i <= N; i++)
			delete V[i];
	}
};

stack S;//用栈代替递归实现DFS
int time = 0;

//插入边
void InsertEdge(Graph *G, Edge *E)
{
	//如果第start点的链表为空,则把当前边E作为head
	if(G->V[E->start]->head == NULL || E->end < G->V[E->start]->head->end )
	{
		E->next = G->V[E->start]->head;
		G->V[E->start]->head = E;
	}
	//如果有,加入到链表中,递增顺序排列,便于查重
	else
	{
		//链表的插入
		Edge *e1 = G->V[E->start]->head, *e2 = e1;
		while(e1 && e1->end < E->end)
		{
			e2 = e1;
			e1 = e1->next;
		}
		if(e1 && e1->end == E->end)
			return;
		else
		{
			e2->next = E;
			E->next = e1;
		}
	}
}
//访问某顶点
void DFS_Visit(Graph *G, Vertex *u)
{
	//将u置为灰色
	u->color = GRAY;
	//使全局变量time增值
	time++;
	//将time的新值记录为发现时间
	u->d = time;
	//当前元素出发的第一条边入栈
	Edge *E = u->head;
	if(E)
		S.push(E);
	while(!S.empty())
	{
		//取栈顶元素,注意区别于出队列
		Edge *e = S.top();
		//检查和栈顶元素相邻的每个顶点v
		Vertex *v = G->V[e->end];//v为指向第e->end个点的链表的指针
		//如果顶点为白色
		if(v->color == WHITE)
		{
			//递归访问顶点
			time++;
			v->d = time;
			v->color = GRAY;
			v->p = u;
			e->type = 1;//树边
			//将下一条边入栈,下一条边可能有两种情况
			if(v->head)
				S.push(v->head);
			else
			{
				while(e && e->next == NULL)
				{
					time++;
					G->V[e->end]->f = time;
					G->V[e->end]->color = BLACK;
					S.pop();
					if(S.empty())e = NULL;
					else e = S.top();
				}
				if(e && e->next)
					S.push(e->next);
			}

		}
		else
		{
			//判断边的类型
			if(v->color == BLACK)
			{
				if(u->d < v->d)
					e->type = 3;
				else
					e->type = 4;
			}
			else if(v->color == GRAY)
				e->type = 2;
			//出栈,并将下一条边入栈
			while(e && e->next == NULL)
			{
				time++;
				G->V[e->start]->f = time;
				G->V[e->start]->color = BLACK;
				S.pop();
				if(S.empty())e = NULL;
				else e = S.top();
			}
			if(e && e->next)
			{
				S.pop();
				S.push(e->next);
			}
		}
	}
}
//深度优先搜索
void DFS(Graph *G)
{
	int i;
	//对每个顶点初始化
	for(i = 1; i <= N; i++)
	{
		G->V[i]->color = WHITE;
		G->V[i]->p = NULL;
	}
	//时间戳初始化
	time = 0;
	//依次检索V中的顶点,发现白色顶点时,调用DFS_Visit访问该顶点
	for(i = 1; i <= N; i++)
	{
		if(G->V[i]->color == WHITE)
			DFS_Visit(G, G->V[i]);
	}
}
//输出
void Print(Graph *G)
{
	int i;
	//遍历每个顶点
	for(i = 1; i <= N; i++)
	{
		cout<V[i]->head;
		while(e)
		{
			cout<end<<' ';
			e = e->next;
		}
		cout<>start>>end;
		E = new Edge(start-'p', end-'p');
		InsertEdge(G, E);
		//无向图,要加两条边
		//		E = new Edge(end, start);
		//		InsertEdge(G, E);
	}
	Print(G);
	//深度优先搜索
	DFS(G);
	//输出每个顶点的第一次访问时间和访问结束的时间
	for(i = 1; i <= N; i++)
	{
		cout<V[i]->d<<' '<V[i]->f<V[i]->head;
		while(e)
		{
			cout<start+'p')<<"->"<end+'p')<<": ";
			switch (e->type)
			{
			case 1:
				cout<<"树边"<next;
		}
	}
	return 0;
}



你可能感兴趣的:(数据结构和算法)