圖的兩種遍歷方式: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;
		}
	}
}

 

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