📜  克隆具有多个连接组件的无向图

📅  最后修改于: 2021-04-21 22:48:04             🧑  作者: Mango

给定具有多个连接组件的无向图,任务是克隆图。在此处可以看到使用单个连接的组件克隆图。

例子:

An example of an undirected graph 
with 3 connected components:

方法:
想法是遵循发布克隆连接图的相同方法,但是对于每个节点,这样我们就可以克隆具有多个连接组件的图。

我们将使用GraphNode类和Graph类。 Graph类是强制性的,因为我们可能有多个连接的组件(请参见上面的示例),并且我们不能仅以GraphNode作为输入来处理它们。对于Graph类,我们实际需要的是GraphNodes列表。两种方法都可以列出节点列表而不是创建类。

为了跟踪访问的节点,我们需要一个数据结构。映射是合适的映射,因为我们可以从“旧”节点映射到“新”节点(克隆节点)。因此,我们定义了一个main函数,它创建地图,并使用一个辅助函数来填充它。创建地图后,可以使用地图中的克隆节点创建新图。
helper函数将在节点之间建立连接(除了填充地图外)。当我们处理整个连接的组件时,将采用类似的BFS方法。

注意,在main函数,我们没有为Graph中的每个节点调用helper函数。如果该节点存储在地图中,则意味着我们已经访问了该节点并处理了其连接的组件,因此无需再次重复这些步骤。
为了检查图是否已正确克隆,我们可以打印节点的内存地址,并对其进行比较以查看是否已克隆或已复制它们。

下面是上述方法的实现:

C++14
// C++ implementation of the approach
#include 
using namespace std;
 
// GraphNode class represents each
// Node of the Graph
class GraphNode
{
    int data;
    list children;
     
    // Constructor to initialize the
    // node with value
    public:
        GraphNode(int data)
        {
            this->data = data;
        }
         
        // Function to add a child to the
        // current node
        void addChild(GraphNode *node)
        {
            this->children.push_back(node);
        }
         
        // Function to return a list of children
        // for the current node
        list getChildren()
        {
            return children;
        }
         
        // Function to set the node's value
        void setData(int data)
        {
            this->data = data;
        }
         
        // Function to return the node's value
        int getData()
        {
            return data;
        }
};
 
// Class to represent the graph
class Graph
{
    list nodes;
     
    public:
        Graph(){}
         
        // Constructor to set the graph's nodes
        Graph(list nodes)
        {
            this->nodes = nodes;
        }
         
        // Function to add a node to the graph
        void addNode(GraphNode *node)
        {
            this->nodes.push_back(node);
        }
         
        // Function to return the list of nodes
        // for the graph
        list getNodes()
        {
            return this->nodes;
        }
};
 
class GFG{
     
// Function to clone the graph
// Function to clone the connected components
void cloneConnectedComponent(GraphNode *node,
                             map &map)
{
    queue queue;
    queue.push(node);
     
    while (!queue.empty())
    {
        GraphNode *current = queue.front();
        queue.pop();
        GraphNode *currentCloned = NULL;
         
        if (map.find(current) != map.end())
        {
            currentCloned = map[current];
        }
        else
        {
            currentCloned = new GraphNode(
                current->getData());
            map[current] = currentCloned;
        }
         
        list children = current->getChildren();
        for(auto child : children)
        {
            if (map.find(child) != map.end())
            {
                currentCloned->addChild(map[child]);
            }
            else
            {
                GraphNode *childCloned = new GraphNode(
                    child->getData());
                map[child] = childCloned;
                currentCloned->addChild(childCloned);
                queue.push(child);
            }
        }
    }
}
 
public:
    Graph *cloneGraph(Graph *graph)
    {
        map mapp;
        for(auto node : graph->getNodes())
        {
            if (mapp.find(node) == mapp.end())
                cloneConnectedComponent(node, mapp);
        }
        Graph *cloned = new Graph();
        for(auto current : mapp)
            cloned->addNode(current.second);
         
        return cloned;
    }
 
// Function to build the graph
Graph *buildGraph()
{
     
    // Create graph
    Graph *g = new Graph();
     
    // Adding nodes to the graph
    GraphNode *g1 = new GraphNode(1);
    g->addNode(g1);
    GraphNode *g2 = new GraphNode(2);
    g->addNode(g2);
    GraphNode *g3 = new GraphNode(3);
    g->addNode(g3);
    GraphNode *g4 = new GraphNode(4);
    g->addNode(g4);
    GraphNode *g5 = new GraphNode(5);
    g->addNode(g5);
    GraphNode *g6 = new GraphNode(6);
    g->addNode(g6);
     
    // Adding edges
    g1->addChild(g2);
    g1->addChild(g3);
    g2->addChild(g1);
    g2->addChild(g4);
    g3->addChild(g1);
    g3->addChild(g4);
    g4->addChild(g2);
    g4->addChild(g3);
    g5->addChild(g6);
    g6->addChild(g5);
     
    return g;
}
 
// Function to print the connected components
void printConnectedComponent(GraphNode *node,
                         set &visited)
{
    if (visited.find(node) != visited.end())
        return;
    queue q;
    q.push(node);
     
    while (!q.empty())
    {
        GraphNode *currentNode = q.front();
        q.pop();
         
        if (visited.find(currentNode) != visited.end())
            continue;
             
        visited.insert(currentNode);
        cout << "Node " << currentNode->getData()
             << " - " << currentNode << endl;
        for(GraphNode *child : currentNode->getChildren())
        {
            cout << "\tNode " << child->getData()
                 << " - " << child << endl;
            q.push(child);
        }
    }
}
};
 
// Driver code
int main()
{
    GFG *gfg = new GFG();
    Graph *g = gfg->buildGraph();
     
    // Original graph
    cout << "\tINITIAL GRAPH\n";
    set visited;
    for(GraphNode *n : g->getNodes())
        gfg->printConnectedComponent(n, visited);
     
    // Cloned graph
    cout << "\n\n\tCLONED GRAPH\n";
    Graph *cloned = gfg->cloneGraph(g);
    visited.clear();
    for(GraphNode *node : cloned->getNodes())
        gfg->printConnectedComponent(node, visited);
}
 
// This code is contributed by sanjeev2552


Java
// Java implementation of the approach
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
 
// Class to represent the graph
class Graph {
 
    private List nodes;
 
    // Constructor to create an empty ArrayList
    // to store the nodes of the graph
    public Graph()
    {
        this.nodes = new ArrayList();
    }
 
    // Constructor to set the graph's nodes
    public Graph(List nodes)
    {
        this.nodes = nodes;
        this.nodes = new ArrayList();
    }
 
    // Function to add a node to the graph
    public void addNode(GraphNode node)
    {
        this.nodes.add(node);
    }
 
    // Function to return the list of nodes
    // for the graph
    public List getNodes()
    {
        return this.nodes;
    }
}
 
// GraphNode class represents each
// Node of the Graph
class GraphNode {
 
    private int data;
    private List children;
 
    // Constructor to initialize the node with value
    public GraphNode(int data)
    {
        this.data = data;
        this.children = new ArrayList();
    }
 
    // Function to add a child to the current node
    public void addChild(GraphNode node)
    {
        this.children.add(node);
    }
 
    // Function to return a list of children
    // for the current node
    public List getChildren()
    {
        return children;
    }
 
    // Function to set the node's value
    public void setData(int data)
    {
        this.data = data;
    }
 
    // Function to return the node's value
    public int getData()
    {
        return data;
    }
}
 
public class GFG {
 
    // Function to clone the graph
    public Graph cloneGraph(Graph graph)
    {
        Map map
            = new HashMap();
        for (GraphNode node : graph.getNodes()) {
            if (!map.containsKey(node))
                cloneConnectedComponent(node, map);
        }
 
        Graph cloned = new Graph();
        for (GraphNode current : map.values())
            cloned.addNode(current);
 
        return cloned;
    }
 
    // Function to clone the connected components
    private void cloneConnectedComponent(GraphNode node,
                          Map map)
    {
        Queue queue = new LinkedList();
        queue.add(node);
 
        while (!queue.isEmpty()) {
            GraphNode current = queue.poll();
            GraphNode currentCloned = null;
            if (map.containsKey(current)) {
                currentCloned = map.get(current);
            }
            else {
                currentCloned = new GraphNode(current.getData());
                map.put(current, currentCloned);
            }
 
            List children = current.getChildren();
            for (GraphNode child : children) {
                if (map.containsKey(child)) {
                    currentCloned.addChild(map.get(child));
                }
                else {
                    GraphNode childCloned
                        = new GraphNode(child.getData());
                    map.put(child, childCloned);
                    currentCloned.addChild(childCloned);
                    queue.add(child);
                }
            }
        }
    }
 
    // Function to build the graph
    public Graph buildGraph()
    {
 
        // Create graph
        Graph g = new Graph();
 
        // Adding nodes to the graph
        GraphNode g1 = new GraphNode(1);
        g.addNode(g1);
        GraphNode g2 = new GraphNode(2);
        g.addNode(g2);
        GraphNode g3 = new GraphNode(3);
        g.addNode(g3);
        GraphNode g4 = new GraphNode(4);
        g.addNode(g4);
        GraphNode g5 = new GraphNode(5);
        g.addNode(g5);
        GraphNode g6 = new GraphNode(6);
        g.addNode(g6);
 
        // Adding edges
        g1.addChild(g2);
        g1.addChild(g3);
        g2.addChild(g1);
        g2.addChild(g4);
        g3.addChild(g1);
        g3.addChild(g4);
        g4.addChild(g2);
        g4.addChild(g3);
        g5.addChild(g6);
        g6.addChild(g5);
 
        return g;
    }
 
    // Function to print the connected components
    public void printConnectedComponent(GraphNode node,
                                        Set visited)
    {
        if (visited.contains(node))
            return;
 
        Queue q = new LinkedList();
        q.add(node);
 
        while (!q.isEmpty()) {
            GraphNode currentNode = q.remove();
            if (visited.contains(currentNode))
                continue;
            visited.add(currentNode);
            System.out.println("Node "
                               + currentNode.getData() + " - " + currentNode);
            for (GraphNode child : currentNode.getChildren()) {
                System.out.println("\tNode "
                                   + child.getData() + " - " + child);
                q.add(child);
            }
        }
    }
 
    // Driver code
    public static void main(String[] args)
    {
        GFG gfg = new GFG();
        Graph g = gfg.buildGraph();
 
        // Original graph
        System.out.println("\tINITIAL GRAPH");
        Set visited = new HashSet();
        for (GraphNode n : g.getNodes())
            gfg.printConnectedComponent(n, visited);
 
        // Cloned graph
        System.out.println("\n\n\tCLONED GRAPH\n");
        Graph cloned = gfg.cloneGraph(g);
        visited = new HashSet();
        for (GraphNode node : cloned.getNodes())
            gfg.printConnectedComponent(node, visited);
    }
}


输出:
INITIAL GRAPH
Node 1 - GraphNode@232204a1
    Node 2 - GraphNode@4aa298b7
    Node 3 - GraphNode@7d4991ad
Node 2 - GraphNode@4aa298b7
    Node 1 - GraphNode@232204a1
    Node 4 - GraphNode@28d93b30
Node 3 - GraphNode@7d4991ad
    Node 1 - GraphNode@232204a1
    Node 4 - GraphNode@28d93b30
Node 4 - GraphNode@28d93b30
    Node 2 - GraphNode@4aa298b7
    Node 3 - GraphNode@7d4991ad
Node 5 - GraphNode@1b6d3586
    Node 6 - GraphNode@4554617c
Node 6 - GraphNode@4554617c
    Node 5 - GraphNode@1b6d3586


    CLONED GRAPH

Node 1 - GraphNode@74a14482
    Node 2 - GraphNode@1540e19d
    Node 3 - GraphNode@677327b6
Node 2 - GraphNode@1540e19d
    Node 1 - GraphNode@74a14482
    Node 4 - GraphNode@14ae5a5
Node 3 - GraphNode@677327b6
    Node 1 - GraphNode@74a14482
    Node 4 - GraphNode@14ae5a5
Node 4 - GraphNode@14ae5a5
    Node 2 - GraphNode@1540e19d
    Node 3 - GraphNode@677327b6
Node 6 - GraphNode@7f31245a
    Node 5 - GraphNode@6d6f6e28
Node 5 - GraphNode@6d6f6e28
    Node 6 - GraphNode@7f31245a