简体   繁体   English

使用BFS克隆图形(无向)

[英]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:- 程序错误的地方:

  1. For self-cycle you will be getting Wrong output. 对于自循环,您将得到错误的输出。 As you make self-cycle twice by making back link to node. 当您通过返回到节点的链接进行两次自循环时。

  2. It is not necessary that if node A is having neighbor B then B will also have node A as neighbor. 如果节点A具有邻居BB不必也将节点A作为邻居。 But for every node you are just pushing it neighbor but also pushing node in neighbor's neighbor, which is wrong. 但是对于每个节点,您都只是将其推向邻居,而且还将节点推向邻居的邻居,这是错误的。

  3. 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.

相关问题 使用 BFS 找到一个循环并将其顶点保存在一个无向、未加权的图中 - Finding a cycle and saving its vertices in an undirected, unweighted graph using BFS 我修改了 BFS 以在加权无向图中找到最短路径而不是使用 Dijkstra 的算法并且它有效 - I modified BFS to find shortest path in weighted undirected graph instead using Dijkstra's algo and it worked 竞争编码的问题。 无向图的 BFS。 获得西澳 - Problem of competitive coding. BFS of undirected graph. Getting WA 使用 dfs 在无向图中循环 - Cycle in an undirected graph using dfs 我可以使用 bfs 技术在无向加权图中找到最短路径吗? 而不是 dijkstra 的算法? - Can i use the bfs technique for finding the shortest path in an undirected weighted graph? Instead of dijkstra's algo? 使用DFS检查无向图中的循环吗? - Checking for a cycle in an undirected graph using DFS? Boost Graph-使用有向边和无向边 - Boost Graph - using both directed and undirected edges 使用迭代DFS在无向图中检测循环? - Detecting cycle in an undirected graph using iterative DFS? 检查是否使用BFS连接图形并打印MST - To check if a graph is connected using BFS and print MST 使用STL在C ++中实现图形和BFS - Implementing graph and BFS in C++ using STL
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM