[英]Clone a graph using BFS (undirected)
I wrote a simple algorithm to clone an undirected graph using BFS, but there seem to be some logic wrong that I can't figure out. 我写了一个简单的算法来使用BFS克隆无向图,但是似乎有些逻辑错误我无法弄清楚。 Can some one take a look? 可以看看吗?
The idea is to visit each node and copy them only once, after copying a node, check if its neighbor is not copied, enqueue that neighbor; 这个想法是访问每个节点并只复制一次,复制一个节点后,检查是否没有复制它的邻居,将那个邻居排入队列; if its neighbor is already copied, put them into each others' neighbor vector. 如果其邻居已被复制,则将它们放入彼此的邻居向量中。
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];
}
Here's the node struct: 这是节点结构:
/**
* Definition for undirected graph.
* struct UndirectedGraphNode {
* int label;
* vector<UndirectedGraphNode *> neighbors;
* UndirectedGraphNode(int x) : label(x) {};
* };
*/
Here's the OJ I'm practicing with: https://leetcode.com/problems/clone-graph/ 这是我正在练习的OJ: https : //leetcode.com/problems/clone-graph/
First of all you have to handle NULL
node case separately because in your code you will return m[NULL]
if input graph is NULL
which can cause runtime error
. 首先,您必须分别处理NULL
节点的情况,因为如果输入图为NULL
,则在代码中将return m[NULL]
,这可能会导致runtime error
。
Have a look at below code I have commented where I have added and deleted the code and why I have added and deleted the code. 看看下面的代码,我评论了添加和删除代码的位置以及添加和删除代码的原因。
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;
}
Edit:- 编辑:-
Where your program is wrong:- 程序错误的地方:
For self-cycle you will be getting Wrong output. 对于自循环,您将得到错误的输出。 As you make self-cycle twice by making back link to node. 当您通过返回到节点的链接进行两次自循环时。
It is not necessary that if node A
is having neighbor B
then B
will also have node A
as neighbor. 如果节点A
具有邻居B
则B
不必也将节点A
作为邻居。 But for every node you are just pushing it neighbor but also pushing node in neighbor's neighbor, which is wrong. 但是对于每个节点,您都只是将其推向邻居,而且还将节点推向邻居的邻居,这是错误的。
If Node are not processed then you are just pushing it into queue not making any link between current node and unprocessed node. 如果未处理节点,那么您只是将其推入队列,而不在当前节点和未处理的节点之间建立任何链接。
For more details see execution of your code :- 有关更多详细信息,请参见代码执行:
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.