问题
给定一个无向图,对该无向图进行拷贝,图中每个结点包含一个label 域和一个用来记录相临节点的vector容器。假设label是唯一的
。
分析
在这之前,我们回忆图的遍历算法,宽度优先(BFS)或深度优先(DFS)。这里我们以深度优先为例来进行分析,首先看代码。
//dfs visit graph
typedef UndirectedGraphNode ufn;
typedef hash_map<ufn*, ufn*> copyedMap;
void dfs(ufn *node, hash_set<ufn *>& visited)
{
if(node == NULL)
return;
if(visited.find(node) == visited.end())
{
cout << node->label << " ";
visited.insert(node);
}
for (int i = 0; i < node->neighbors.size(); ++i)
{
dfs(node->neighbors[i], visited);
}
}
void visitGraph( ufn *first)
{
if(first == NULL)
return;
hash_set<ufn* > visited;
visited.clear();
dfs(first,visited);
return;
}
dfs 和 bfs访问图以及树结构是基本的也是必须掌握的,这里不展开赘述。
仔细体会下这个dfs访问结点的函数,我们是不是得到什么启示呢?在copy 节点的时候,是不是也恰恰就是visit 模式?
实现:
ufn* dfs(UndirectedGraphNode* node,copyedMap& copyedNodes){
if(node == NULL)
return NULL;
if(copyedNodes.find(node) != copyedNodes.end())
return copyedNodes[node];
else
{
ufn *copyed = new ufn(node->label);
copyedNodes[node] = copyed;
for (int i = 0; i < node->neighbors.size(); ++i)
{
copyed->neighbors.push_back(dfs(node->neighbors[i],copyedNodes));
}
return copyed;
}
}
UndirectedGraphNode* cloneGraph(UndirectedGraphNode *node){
hash_map<UndirectedGraphNode*, UndirectedGraphNode*> copyedNodes;
return dfs(node, copyedNodes);
}
代码是不是属于同一种模式?
总结:
对于树的三种访问形式(前,中,后序),一定要熟记于胸,这里不是指代码,而是思想,直白点就是模式,很多复杂的,看似生疏的问题,都是从这里衍生出来的,只不过不再是简单的print,而是要做些其他的额外工作而已。以及这里提到的DFS,BFS。同理,对于图也是如此,当然图而言就是DFS,BFS。
附
ufn * createGraph(const string &graph){
if(graph.size() == 0)
return NULL;
int i = 0;
//assume the label is different.
hash_map<char, ufn*> createdNodes;
createdNodes.clear();
while (i < graph.size())
{
ufn* node;
if(createdNodes.find(graph[i]) != createdNodes.end())
node = createdNodes[graph[i]];
else
{
node = new ufn(graph[i] - '0');
createdNodes[graph[i]] = node;
}
++i;
while (i < graph.size() && graph[i] != '#')
{
if(graph[i] != ',')
{
if(createdNodes.find(graph[i]) != createdNodes.end())
node->neighbors.push_back(createdNodes[graph[i]]);
else
{
createdNodes[graph[i]] = new ufn(graph[i] - '0');
node->neighbors.push_back(createdNodes[graph[i]]);
}
}
++i;
}
++i;//skip the '#'
}
return createdNodes[graph[0]];
}