新图的深层复制构造函数

时间:2016-09-18 14:37:58

标签: c++ shared-ptr copy-constructor deep-copy directed-graph

我试图访问Node Struct中的edges_,所以我可以执行for循环将边复制到我的复制构造函数的新图形对象。

当我尝试访问节点中的edges_时,我收到以下错误,这让我很困惑。

tests/Graph.tem:280:24: error: ‘struct std::pair<const std::__cxx11::basic_string<char>, std::shared_ptr<gdwg::Graph<std::__cxx11::basic_string<char>, int>::Node> >’ has no member named ‘edges_’
   for (auto edge: node.edges_) {
                   ~~~~~^~~~~~

我试图做一个复制构造函数,将图形中的节点和边缘深度复制到新的图形对象:

template <typename N, typename E>
Graph<N, E>::Graph(const Graph &g):
    nodes_{g.nodes_}
    {

        for (auto node: g.nodes_) {

            for (auto edge: node.edges_) {

            }

        }


    }

以下是我的Graph类:

template <typename N, typename E> class Graph {

    private:
        struct Node;
        struct Edge;

        struct Node {
            N val_;
            int numEdges_;
            int numIncomingEdges_;
            std::set<std::shared_ptr<Edge>> edges_;
            std::set<std::shared_ptr<Edge>> incomingEdges_;
            Node() {}
            Node(const N x) : val_{x} { numEdges_=0; numIncomingEdges_=0; }
            void printNode(N n);
            ~Node();
            void update();
        };

        struct Edge {
            std::weak_ptr<Node> orig;
            std::weak_ptr<Node> dest;
            E val_;
            Edge(std::shared_ptr<Node> o, std::shared_ptr<Node> d, E x);
            Edge() {};
            void printEdge();
            ~Edge();
        };

首先,如何访问它来执行深层复制?似乎有一些ptr问题。其次,是否有一种简单的方法可以深度复制存储在节点内的边缘?

1 个答案:

答案 0 :(得分:1)

对于编译器消息,您应该将for (auto edge: node.edges_)替换为for (auto edge: node.second->edges_)

要执行深层复制,您需要g的源节点与副本的节点之间的关联映射。

这是我为深拷贝构造函数编写的代码的概念(我还没有尝试编译它)。

template <typename N, typename E>
Graph<N, E>::Graph(const Graph &g):
    nodes_{g.nodes_}
    {   std::map<Node*, Node*> associativeMap;
        typename std::map<N, std::shared_ptr<Node>>::const_iterator
            thisIter(nodes_.begin()), sourceIter(g.nodes_.begin()),
            thisIterEnd(nodes_.end()), sourceIterEnd(g.nodes_.end());
        for (; thisIter != thisIterEnd; ++thisIter) {
            associativeMap.insert(std::make_pair(&*(sourceIter->second), &*(thisIter->second));
            ++sourceIter;
        }

        thisIter = nodes_.begin();
        for (auto sourceNode: g.nodes_) {
            Node* thisNode = &*thisIter->second;
            for (auto sourceEdge: sourceNode.second->edges_)
               addEdge(*thisNode, *associativeMap[&*sourceEdge->dest], ...);
            ++thisIter;
        }
    }

它基于addEge方法,签名为void addEdge(Node& origin, Node& destination, ...)

如果您的Graph :: nodes_很快就会被排序,并且addEdge可以从密钥中检索节点 - 如果其签名是bool addEdge(const N& orig, const N& dest, const E& val) - ,则associativeMap不再有用。在这种情况下,代码更简单。

template <typename N, typename E>
Graph<N, E>::Graph(const Graph &g): nodes_{g.nodes_}
{  for (auto sourceNode: g.nodes_) {
      for (auto sourceEdge: sourceNode.second->edges_)
         addEdge(sourceNode.second->val_, sourceEdge->dest.lock()->val_, sourceEdge->val_);
   }
}