图的两种遍历方式:DFS和BFS -----摘自《天勤数据结构高分笔记》并做了写修改,使用了STL中的数据结构实现

//图的邻接表示
static  struct ArcNode {
	int adjvex;					//该边所指向的节点的位置
	struct ArcNode* nextarc;	               //指向下一条边的指针
	int info;				       //该边的信息
};

static struct VNode {
	char data;			               //顶点信息
	ArcNode* firstArc;			      //指向第一条边的指针
};

static struct AGraph {
	vector<VNode> adjList;		             //邻接表	
	int n, e;			 	     //顶点数和边数
};


//图的深度遍历DFS

vector<bool> visit;

void DFS(AGraph * G, int v) 
{
	ArcNode* p = NULL;
	visit[v] = true;

	//Visit(s);				//顶点的访问函数

	p = G->adjList[v].firstArc;
	while (p != NULL)
	{
		if (!visit[p->adjvex])
		{
			DFS(G, p->adjvex);  //(1)
		}
		p = p->nextarc;  // 指向下一条边
	}

}
/*
	对比二叉树的前序遍历对比
	void Preorder(btNode* p)
	{
		if(NULL != p)
		{
			visit(p);
			preorder(p->lchild);  // (2)
			preorder(p->rchild);  //(3)
		}
	}
	说明一下:图的DFS类似于二叉树的先序遍历。对比二者,不难发现:二叉树中的(2)和(3)两句为递归访问当前节点的两个分支,
	对应与图的DFS代码段中就是while循环内的语句(1),实现了递归地访问当前顶点的多个分支,两者十分相似。区别在于:二叉树
	只需要递归地访问当前节点的两个分支,图的深度优先搜索遍历则是要递归地访问多个分支

*/


//图的广度优先遍历
void BFS(AGraph* G, int v, vector<bool>& visit)
{
	fill(visit.begin(), visit.end(), false);		//清零visit数组
	ArcNode* p = NULL;
	queue<int> q;

	//访问顶点V,注意一定是在节点入队之前设置访问标记,这样才能避免节点重复入队列,类似于树的先序遍历
    //如果是在节点出队列的时候设置访问标记,这就很大可能导致节点重复进入队列,降低算法的效率
	visit[v] = true;

	q.push(v);
	while (!q.empty())
	{
		auto front = q.front();  //这里是节点出队列的地方
		q.pop();

		p = G->adjList[front].firstArc;
		
		while (p != NULL)
		{
			if (visit[p->adjvex] == false)
			{
				//此处加上访问顶点p->adjvex的函数

				visit[p->adjvex] = true;  //设置新节点的访问标记

				q.push(p->adjvex);   //该顶点入队
			}
			p = p->nextarc;
		}
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章