簡體   English   中英

在使用智能指針的有向加權圖中刪除節點的邊

[英]Deleting edges for a node in a directed weighted graph that uses smart pointers

我對共享指針還很陌生,正在嘗試從圖中刪除一個節點。 當我刪除一個節點時,存儲在該節點中的傳入和傳出邊緣將被刪除。 但是,我還需要刪除以前連接到已刪除節點的節點的出站和入站邊緣(分別是已刪除節點的入站和出站邊緣),我將其稱為鏈接節點。

下面的代碼顯示了我的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; }
            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();
        };
..... Some code for node and edge iterators

private:
        std::map< N, std::shared_ptr<Node> > nodes_;

};

對於要刪除節點的類:

template <typename N, typename E>
void Graph<N, E>::deleteNode(const N& node) noexcept {
    auto findNode = nodes_.find(node);
    if (findNode != nodes_.end()) {

        // find the node which has incoming edges into the deleted node and delete its edges
        for (auto edge: findNode->second->incomingEdges_) { // for each edge in node's incomingEdges_

            // get the origin node of incoming edge to deleted node through dest.lock()
            auto originNodeOfIncomingEdge = edge->dest.lock();

            auto nodeVal1 = originNodeOfIncomingEdge->val_;
            std::cout << "Print out value of origin node of incoming edge to deleted node: " << nodeVal1 << std::endl;

            auto findLinkingNode1 = nodes_.find(nodeVal1);
            std::cout << "size of edges_ in linking node before deleting its outgoing edge (which is the incoming edge of deleted node): " << findLinkingNode1->second->edges_.size() << std::endl;

            auto findEdge = findLinkingNode1->second->edges_.find(edge);
            findLinkingNode1->second->edges_.erase(findEdge);

            std::cout << "size of edges_ in linking node after deleting its outgoing edge (which is the incoming edge of deleted node): " << findLinkingNode1->second->edges_.size() << std::endl;
            --findLinkingNode1->second->numEdges_;

        }

... similar code to above for deleting the node that has outgoing edges from deleted node going into it

        findNode->second.reset(); // deletes managed object of the shared_ptr
        nodes_.erase(findNode); // removes the node from the map container

    }
}

因此,最讓我感到困惑的是這部分,在這里我試圖從for循環中刪除邊緣以刪除鏈接節點中的邊緣。

            auto findEdge = findLinkingNode1->second->edges_.find(edge);
            findLinkingNode1->second->edges_.erase(findEdge);

但是我不斷收到與shared_ptr相關的錯誤。 首先與指針有關:

test8c(2863,0x7fff78df2000) malloc: *** error for object 0x7ffda2403350: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6

以前,我這部分的代碼是findLinkingNode1->second->edges_.erase(edge); 沒有findEdge。 我能夠編譯而沒有任何錯誤,但未刪除邊緣。

有人可以指導我如何成功地從edges_刪除邊緣嗎? edges_被聲明為std::set<std::shared_ptr<Edge>> edges_; 如Graph類所示。

事物的結構方式不是很有效。 您的Node的析構函數將需要:

  1. 遍歷要銷毀的Node中的每個Edge

  2. 對於每個Edge get()另一個Node

  3. 在其他Node的列表中找到相同的Edge ,然后將其刪除。

如果這是經常的操作,我建議進行以下重構:

  1. 您的Edgeshared_ptr保留到您的Node

  2. 您的Node持有Edgeweak_ptr

因此,要刪除Node ,請遍歷該節點的Edge ,然后將其刪除。 刪除所有Edge之后,到Node的所有shared_ptr都超出范圍,並且該節點被銷毀。

如果這不切實際,那么重新設計的方法就不那么激烈了:

  1. 為每個Edge分配某種唯一的標識符。 一個簡單的遞增計數器就可以了,並且有可能在Edge的構造函數中自動進行處理。

  2. 使用其唯一標識符引用所有Edge ,而不是Edgeshared_ptrstd::set ,而是用標識符的std::map替換為Edgeshared_ptr 當銷毀特定的Node時,從每個Node移除每個Edge變得很簡單。

除了實現離散標識符之外,還需要格外小心地使用指向Edge的原始指針,並將std::less<Edge *>作為其嚴格的弱排序比較器,作為每個邊緣的即興唯一標識符。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM