寬度優先搜索輕鬆實現克隆圖

 

目錄

 

 

一、簡介

二、圖的表示

1、鄰接矩陣

2、邊的數組

3、鄰接鏈表

三、實戰

1、題目概述      

2、實現方法1

3、實現方法2

四、總結


一、簡介

        寬度優先搜索算法(又稱廣度優先搜索)是最簡便的圖的搜索算法之一,這一算法也是很多重要的圖的算法的原型。Dijkstra單源最短路徑算法和Prim最小生成樹算法都採用了和寬度優先搜索類似的思想。其別名又叫BFS,屬於一種盲目搜尋法,目的是系統地展開並檢查圖中的所有節點,以找尋結果。換句話說,它並不考慮結果的可能位置,徹底地搜索整張圖,直到找到結果爲止。下面我使用寬度優先搜索算法實現克隆圖。

二、圖的表示

1、鄰接矩陣

      對於N個點的圖,需要N×N的矩陣表示點與點之間是否有邊的存在。這種表示法的缺點是浪費空間,尤其是對於N×N的矩陣是稀疏矩陣,即邊的數目遠遠小於N×N的時候,浪費了巨大的存儲空間。

                                                 

                                                                               圖 1

2、邊的數組

       使用一個Edge類,它含有兩個int實例變量。這種表示方法很簡潔但獲取頂點v所有鄰接頂點要檢查圖中所有的邊。這種表示方法使用較少。

3、鄰接鏈表

         對於任何一個node A,外掛一個鄰接鏈表,如果存在 A->X這樣的邊,就將X鏈入鏈表。 這種表示方法的優點是節省空間,缺點是所有鏈表都存在的缺點,地址空間的不連續造成緩存命中降低,性能有不如臨界矩陣這樣的數組。我們使用鄰接鏈表來表示此次算法的實現。

   

                                       

                                                                                 圖  2

 

三、實戰

1、題目概述      

題目:給你無向連通圖中一個節點,實現該圖的 深拷貝(克隆)。

我們使用鄰接鏈表來表示此次算法的實現。

class Node {
public:
int val;
vector<Node*> neighbors;

Node() {
val = 0;
neighbors = vector<Node*>();
}

Node(int _val) {
val = _val;
neighbors = vector<Node*>();
}

Node(int _val, vector<Node*> _neighbors) {
val = _val;
neighbors = _neighbors;
}
};

2、實現方法1

        我們可以利用寬度優先搜索遍歷圖,先把圖的節點都生成一遍,把生成的節點和原始節點存到hash表中(clone nodes)。然後再遍歷一遍hash表,生成邊(clone edges )。

Node* cloneGraph(Node* node) {


		if (node == NULL)
		{
			return NULL;
		}
		unordered_map<Node*, Node*> mapNode;
		std::queue<Node*> queueNode;
		queueNode.push(node);

		Node*pnode = node;
       //clone nodes
		while (!queueNode.empty())
		{
			node = queueNode.front();
			queueNode.pop();

			if (mapNode.find(node) != mapNode.end())
			{
				continue;
			}

			mapNode[node] = new Node(node->val);

			int s = node->neighbors.size();
			for (int i = 0; i < s; i++)
			{


				queueNode.push(node->neighbors[i]);
			}

		}

		//clone edge
		unordered_map<Node*, Node*>::iterator it = mapNode.begin();
		while (it != mapNode.end())
		{

			int s = it->first->neighbors.size();
			for (int i = 0; i < s; ++i)
			{
				it->second->neighbors.push_back(mapNode[it->first->neighbors[i]]);
			}

			++it;
		}
		

		return mapNode[pnode];


	}

3、實現方法2

        我們可以利用寬度優先搜索遍歷圖,把圖的節點和節點的neighbour節點都生成一遍,把生成的節點和原始節點存到hash表中(clone nodes)。在遍歷的同時生成邊(clone edges)。

	Node* cloneGraph2(Node* node) {



		if (node == NULL)
		{
			return NULL;
		}
		unordered_map<Node*, Node*> mapNode;
		std::queue<Node*> queueNode;
		queueNode.push(node);

		Node*pnode = node;

		//clone node and edges
		mapNode[node] = new Node(node->val);
		while (!queueNode.empty())
		{
			node = queueNode.front();
			queueNode.pop();


			int s = node->neighbors.size();
			for (int i = 0; i < s; i++)
			{
				if (mapNode.find(node->neighbors[i]) == mapNode.end())
				{

					mapNode[node->neighbors[i]] = new Node(node->neighbors[i]->val);
					queueNode.push(node->neighbors[i]);
			
				}

				mapNode[node]->neighbors.push_back(mapNode[node->neighbors[i]]);

				
			}

		}


		return mapNode[pnode];


	}

 

四、總結

     深度優先搜索比較簡單,但是可以解決很多問題,克隆圖就可以通過深度優先搜索輕鬆的解決。方法1邏輯上比較清晰,方法2只進行一次遍歷,效率高。

 

 

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