1. 程式人生 > >三、【圖演算法】優先順序搜尋(PFS)

三、【圖演算法】優先順序搜尋(PFS)

最基本而典型的圖搜尋演算法包括:廣度優先搜尋(BFS),深度優先搜尋(DFS),優先順序搜尋等(PFS),本文主要介紹圖的優先順序搜尋(priority-first search,DFS),本文使用的圖資料結構參見之前部落格https://blog.csdn.net/qq_18108083/article/details/84870399

策略:從之前介紹的廣度優先搜尋和深度優先搜尋中,可以發現這兩種演算法的框架具有一定的相似性,這兩種演算法的差異性體現在每一步迭代中對新頂點的選取策略不同,每一種選取策略都等效為,給所有頂點賦予不同的優先順序,而且優先順序隨著演算法的推進不斷調整,在每一步迭代所選取的頂點,都是當時的優先順序最高者,其實這個思想就是所謂的優先順序搜尋

實現:由於整個圖可能具有多個連通域,從單個頂點開始的PFS可能不能遍歷到圖中的所有頂點,所以PFS函式能夠遍歷從頂點s開始的單個連通域,而pfs函式則對所有頂點進行檢查,只要未曾被訪問過,就從該點開始一次新的PFS搜尋,這樣就能保證所有的連通域都能夠被遍歷到。

template<typename Tv, typename Te> template<typename PU> void graph<Tv, Te>::PFS(int s, PU prioUpdater)   //(單個連通域)優先順序搜尋
{
	priority(s) = 0;      //設定s的優先順序最高
	status(s) = VISITED;  //標記頂點s為已經便利的
	cout << "選中的頂點:" << vdata(s) << endl;
	parent(s) = -1;       //這句可以不要,因為reset()已經置-1
	while (true)
	{
		for (int w = firstNbr(s); w > -1; w = nextNbr(s, w))   //遍歷頂點s的所有鄰居
		{
			prioUpdater(this, s, w);  //更新頂點w的優先順序和父頂點
		}
		for (int shortest = INT_MAX, w = 0; w < n; w++)
		{
			if (status(w) == UNDISCOVERED)   //如果頂點w尚未被遍歷
				if (priority(w) < shortest)
				{
					shortest = priority(w);
					s = w;       //更新級數最小的點
				}
		}
		if (status(s) == VISITED) break;   //如果所有頂點均已經訪問,則結束
		status(s) = VISITED; 
		cout << "選中的頂點:"<<vdata(s) << endl;
		cout << parent(s) << endl;
		type(parent(s), s) = TREE;
	}
}

template<typename Tv, typename Te> template<typename PU> void graph<Tv, Te>::pfs(int s, PU prioUpdater)
{
	reset();
	int v = s;
	do
	{
		if (status(v) == UNDISCOVERED)
			PFS(v, prioUpdater);
	} while ((v = (++v%n)) != s);
}

效率:若圖G=(V,E)中共有n個頂點和e條邊,則PFS僅需O(n^2)時間。