克隆无向图
已经讨论了使用随机指针克隆 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
克隆具有多个连通分量的无向图