![](/img/trans.png)
[英]Finding a cycle and saving its vertices in an undirected, unweighted graph using BFS
[英]Clone a graph using BFS (undirected)
我写了一个简单的算法来使用BFS克隆无向图,但是似乎有些逻辑错误我无法弄清楚。 可以看看吗?
这个想法是访问每个节点并只复制一次,复制一个节点后,检查是否没有复制它的邻居,将那个邻居排入队列; 如果其邻居已被复制,则将它们放入彼此的邻居向量中。
UndirectedGraphNode *cloneGraph(UndirectedGraphNode *node) {
//key -> old node, value -> the new copy
unordered_map<UndirectedGraphNode*, UndirectedGraphNode*> m;
//the queue always contains old nodes that haven't been copied
queue<UndirectedGraphNode*> q;
if(node)
q.push(node);
while(!q.empty()) {
UndirectedGraphNode* n = q.front();
q.pop();
if(m.count(n)) continue; // if the node is already copied, continue
// create the copy
m[n] = new UndirectedGraphNode(n->label);
// loop through the neighbors, if it's copied already, add the new copy to new copy's neighbor list
for(UndirectedGraphNode* oldNei : n->neighbors) {
if(m.count(oldNei)) {
UndirectedGraphNode* newNei = m[oldNei];
m[n]->neighbors.push_back(newNei);
newNei->neighbors.push_back(m[n]);
}
else// if not in the map, it's not copied/visited yet
q.push(oldNei);
}
}
return m[node];
}
这是节点结构:
/**
* Definition for undirected graph.
* struct UndirectedGraphNode {
* int label;
* vector<UndirectedGraphNode *> neighbors;
* UndirectedGraphNode(int x) : label(x) {};
* };
*/
这是我正在练习的OJ: https : //leetcode.com/problems/clone-graph/
首先,您必须分别处理NULL
节点的情况,因为如果输入图为NULL
,则在代码中将return m[NULL]
,这可能会导致runtime error
。
看看下面的代码,我评论了添加和删除代码的位置以及添加和删除代码的原因。
UndirectedGraphNode *cloneGraph(UndirectedGraphNode *node) {
// ++ if node is null just return null.
if(node == NULL) return NULL;
unordered_map<UndirectedGraphNode*, UndirectedGraphNode*> m;
queue<UndirectedGraphNode*> q;
// -- if(node) no need to check this as we have checked it above
q.push(node);
// ++ as first input will not have copy so no need to check it in map
// just create a copy and associate it with original node in map.
UndirectedGraphNode *graphCopy = new UndirectedGraphNode(node->label);
m[node] = graphCopy;
while(!q.empty()) {
UndirectedGraphNode* n = q.front();
q.pop();
// -- if(m.count(n)) continue; :- no need to check this condition as we will
// only push non copied node in queue.
// -- m[n] = new UndirectedGraphNode(n->label); :- we will create it inside loop
// loop through the neighbors, if it's copied already, add the new copy to new copy's neighbor list
for(UndirectedGraphNode* oldNei : n->neighbors) {
// if node is processed/ copied earlier then just push it in neighbour of current node
if(m.count(oldNei)) {
UndirectedGraphNode* newNei = m[oldNei];
m[n]->neighbors.push_back(newNei);
// -- newNei->neighbors.push_back(m[n]); no need of making back connection as
// this node has already processed and contains all it neighbour
}
else {// if not in the map, it's not copied/visited yet then create new copy of node here
//and push it into queue
UndirectedGraphNode *p = new UndirectedGraphNode(oldNei->label); // ++ make a copy of node
m[n]->neighbors.push_back(p); // ++ push it to current node neighbour
m[oldNei] = p; // ++ associate copied node with its original one
q.push(oldNei); // push that node to queue
}
}
}
return graphCopy;
}
编辑:-
程序错误的地方:
对于自循环,您将得到错误的输出。 当您通过返回到节点的链接进行两次自循环时。
如果节点A
具有邻居B
则B
不必也将节点A
作为邻居。 但是对于每个节点,您都只是将其推向邻居,而且还将节点推向邻居的邻居,这是错误的。
如果未处理节点,那么您只是将其推入队列,而不在当前节点和未处理的节点之间建立任何链接。
有关更多详细信息,请参见代码执行:
Let's take same graph as of problem:
First node is labeled as 1. Connect node 1 to both nodes 2 and 3.
Second node is labeled as 2. Connect node 2 to node 3.
Third node is labeled as 3. Connect node 3 to node 3 (itself), thus forming a self-cycle.
So original graph will have neighbor like this:
Neighbor 1 -> 2 , 3
Neighbor 2 -> 3
Neighbor 3 -> 3
1
/ \
/ \
2 --- 3
/ \
\_/
Now starting executing your code:
assume 1 as root node
first it will insert 1 in Queue
Q -> [ 1 ]
inside While Loop :-
----------------------------------------------------------------------------------------------------
First Iteration:-
n = 1
Pop : Q -> empty // 1 is poped out so queue is empty now
here node 1 is not in map so you will create a copy of node 1 and save it in map
Map -> (1 , 1C)
Check for neighbour of 1 -> which is 2 & 3
inside for loop both node 2 & 3 is not processed so you will push it in Queue so Queue will became:-
Q -> [2, 3]
----------------------------------------------------------------------------------------------------
Second Iteration:-
n = 2
Pop : Q -> [ 3 ]
Node 2 is not in map-
Create copy of node 2 and push it in map
Map -> (1, 1C) , (2, 2C)
Check for neighbour of 2 -> which is 3
node 3 is not processed till now so push it in Queue
Q -> [3, 3]
----------------------------------------------------------------------------------------------------
Third Tteration:-
n = 3
Pop : Q -> [ 3 ]
node 3 is not in map so-
Create copy of node 3 and push it in map
Map -> (1, 1C) , (2, 2C) , (3, 3C)
Check for neighbour of 3 -> which is 3
Node 3 is also in map so you will create a link between node 3C & 3C which is correct but you will do it twice as you are pushing back node also so in this step you will do as follows
Neighbour 3C -> 3C
Neighbour 3C -> 3C
So over all it will look like
Neighbour 1C ->
Neighbour 2C ->
Neighbour 3C -> 3C, 3C
This is your final result and it different from original
----------------------------------------------------------------------------------------------------
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.