📜  克隆无向图

📅  最后修改于: 2022-05-13 01:57:54.382000             🧑  作者: Mango

克隆无向图

已经讨论了使用随机指针克隆 LinkedList 和二叉树。克隆图背后的想法非常相似。

这个想法是对图进行 BFS 遍历,并在访问节点时创建它的克隆节点(原始节点的副本)。如果遇到已经访问过的节点,则它已经有一个克隆节点。

如何跟踪访问/克隆的节点?
为了维护所有已经创建的节点,需要一个 HashMap/Map。
密钥存储:原始节点的引用/地址
值存储:克隆节点的引用/地址

所有图节点都复制了,如何连接克隆节点?
在访问节点 u 的相邻顶点时,会为u获取相应的克隆节点,让我们称之为cloneNodeU ,现在访问u的所有相邻节点,并为每个邻居找到相应的克隆节点(如果找不到,则创建一个),然后推入cloneNodeU节点的相邻向量。

如何验证克隆图是否正确?
在克隆图之前和之后进行 BFS 遍历。在 BFS 遍历中显示节点的值及其地址/引用。
比较显示节点的顺序,如果值相同但两次遍历的地址/引用不同,则克隆图是正确的。

C++
// A C++ program to Clone an Undirected Graph
#include
using namespace std;
  
struct GraphNode
{
    int val;
  
    //A neighbour vector which contains addresses to
    //all the neighbours of a GraphNode
    vector neighbours;
};
  
// A function which clones a Graph and
// returns the address to the cloned
// src node
GraphNode *cloneGraph(GraphNode *src)
{
    //A Map to keep track of all the
    //nodes which have already been created
    map m;
    queue q;
  
    // Enqueue src node
    q.push(src);
    GraphNode *node;
  
    // Make a clone Node
    node = new GraphNode();
    node->val = src->val;
  
    // Put the clone node into the Map
    m[src] = node;
    while (!q.empty())
    {
        //Get the front node from the queue
        //and then visit all its neighbours
        GraphNode *u = q.front();
        q.pop();
        vector v = u->neighbours;
        int n = v.size();
        for (int i = 0; i < n; i++)
        {
            // Check if this node has already been created
            if (m[v[i]] == NULL)
            {
                // If not then create a new Node and
                // put into the HashMap
                node = new GraphNode();
                node->val = v[i]->val;
                m[v[i]] = node;
                q.push(v[i]);
            }
  
            // add these neighbours to the cloned graph node
            m[u]->neighbours.push_back(m[v[i]]);
        }
    }
  
    // Return the address of cloned src Node
    return m[src];
}
  
// Build the desired graph
GraphNode *buildGraph()
{
    /*
        Note : All the edges are Undirected
        Given Graph:
        1--2
        | |
        4--3
    */
    GraphNode *node1 = new GraphNode();
    node1->val = 1;
    GraphNode *node2 = new GraphNode();
    node2->val = 2;
    GraphNode *node3 = new GraphNode();
    node3->val = 3;
    GraphNode *node4 = new GraphNode();
    node4->val = 4;
    vector v;
    v.push_back(node2);
    v.push_back(node4);
    node1->neighbours = v;
    v.clear();
    v.push_back(node1);
    v.push_back(node3);
    node2->neighbours = v;
    v.clear();
    v.push_back(node2);
    v.push_back(node4);
    node3->neighbours = v;
    v.clear();
    v.push_back(node3);
    v.push_back(node1);
    node4->neighbours = v;
    return node1;
}
  
// A simple bfs traversal of a graph to
// check for proper cloning of the graph
void bfs(GraphNode *src)
{
    map visit;
    queue q;
    q.push(src);
    visit[src] = true;
    while (!q.empty())
    {
        GraphNode *u = q.front();
        cout << "Value of Node " << u->val << "\n";
        cout << "Address of Node " < v = u->neighbours;
        int n = v.size();
        for (int i = 0; i < n; i++)
        {
            if (!visit[v[i]])
            {
                visit[v[i]] = true;
                q.push(v[i]);
            }
        }
    }
    cout << endl;
}
  
// Driver program to test above function
int main()
{
    GraphNode *src = buildGraph();
    cout << "BFS Traversal before cloning\n";
    bfs(src);
    GraphNode *newsrc = cloneGraph(src);
    cout << "BFS Traversal after cloning\n";
    bfs(newsrc);
    return 0;
}


Java
// Java program to Clone an Undirected Graph
import java.util.*;
  
// GraphNode class represents each
// Node of the Graph
class GraphNode
{
    int val;
  
    // A neighbour Vector which contains references to
    // all the neighbours of a GraphNode
    Vector neighbours;
    public GraphNode(int val)
    {
        this.val = val;
        neighbours = new Vector();
    }
}
  
class Graph
{
    // A method which clones the graph and
    // returns the reference of new cloned source node
    public GraphNode cloneGraph(GraphNode source)
    {
        Queue q = new LinkedList();
        q.add(source);
  
        // An HashMap to keep track of all the
        // nodes which have already been created
        HashMap hm =
                        new HashMap();
  
        //Put the node into the HashMap
        hm.put(source,new GraphNode(source.val));
  
        while (!q.isEmpty())
        {
            // Get the front node from the queue
            // and then visit all its neighbours
            GraphNode u = q.poll();
  
            // Get corresponding Cloned Graph Node
            GraphNode cloneNodeU = hm.get(u);
            if (u.neighbours != null)
            {
                Vector v = u.neighbours;
                for (GraphNode graphNode : v)
                {
                    // Get the corresponding cloned node
                    // If the node is not cloned then we will
                    // simply get a null
                    GraphNode cloneNodeG = hm.get(graphNode);
  
                    // Check if this node has already been created
                    if (cloneNodeG == null)
                    {
                        q.add(graphNode);
  
                        // If not then create a new Node and
                        // put into the HashMap
                        cloneNodeG = new GraphNode(graphNode.val);
                        hm.put(graphNode,cloneNodeG);
                    }
  
                    // add the 'cloneNodeG' to neighbour
                    // vector of the cloneNodeG
                    cloneNodeU.neighbours.add(cloneNodeG);
                }
            }
        }
  
        // Return the reference of cloned source Node
        return hm.get(source);
    }
  
    // Build the desired graph
    public GraphNode buildGraph()
    {
        /*
            Note : All the edges are Undirected
            Given Graph:
            1--2
            |  |
            4--3
        */
        GraphNode node1 = new GraphNode(1);
        GraphNode node2 = new GraphNode(2);
        GraphNode node3 = new GraphNode(3);
        GraphNode node4 = new GraphNode(4);
        Vector v = new Vector();
        v.add(node2);
        v.add(node4);
        node1.neighbours = v;
        v = new Vector();
        v.add(node1);
        v.add(node3);
        node2.neighbours = v;
        v = new Vector();
        v.add(node2);
        v.add(node4);
        node3.neighbours = v;
        v = new Vector();
        v.add(node3);
        v.add(node1);
        node4.neighbours = v;
        return node1;
    }
  
    // BFS traversal of a graph to
    // check if the cloned graph is correct
    public void bfs(GraphNode source)
    {
        Queue q = new LinkedList();
        q.add(source);
        HashMap visit =
                          new HashMap();
        visit.put(source,true);
        while (!q.isEmpty())
        {
            GraphNode u = q.poll();
            System.out.println("Value of Node " + u.val);
            System.out.println("Address of Node " + u);
            if (u.neighbours != null)
            {
                Vector v = u.neighbours;
                for (GraphNode g : v)
                {
                    if (visit.get(g) == null)
                    {
                        q.add(g);
                        visit.put(g,true);
                    }
                }
            }
        }
        System.out.println();
    }
}
  
// Driver code
class Main
{
    public static void main(String args[])
    {
        Graph graph = new Graph();
        GraphNode source = graph.buildGraph();
        System.out.println("BFS traversal of a graph before cloning");
        graph.bfs(source);
        GraphNode newSource = graph.cloneGraph(source);
        System.out.println("BFS traversal of a graph after cloning");
        graph.bfs(newSource);
    }
}



用Java输出:
BFS traversal of a graph before cloning
Value of Node 1
Address of Node GraphNode@15db9742
Value of Node 2
Address of Node GraphNode@6d06d69c
Value of Node 4
Address of Node GraphNode@7852e922
Value of Node 3
Address of Node GraphNode@4e25154f

BFS traversal of a graph after cloning
Value of Node 1
Address of Node GraphNode@70dea4e
Value of Node 2
Address of Node GraphNode@5c647e05
Value of Node 4
Address of Node GraphNode@33909752
Value of Node 3
Address of Node GraphNode@55f96302

C++ 中的输出:

BFS Traversal before cloning
Value of Node 1
Address of Node 0x24ccc20
Value of Node 2
Address of Node 0x24ccc50
Value of Node 4
Address of Node 0x24cccb0
Value of Node 3
Address of Node 0x24ccc80

BFS Traversal after cloning
Value of Node 1
Address of Node 0x24cd030
Value of Node 2
Address of Node 0x24cd0e0
Value of Node 4
Address of Node 0x24cd170
Value of Node 3
Address of Node 0x24cd200

克隆具有多个连通分量的无向图