[英]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
的析構函數將需要:
遍歷要銷毀的Node
中的每個Edge
。
對於每個Edge
get()
另一個Node
。
在其他Node
的列表中找到相同的Edge
,然后將其刪除。
如果這是經常的操作,我建議進行以下重構:
您的Edge
將shared_ptr
保留到您的Node
。
您的Node
持有Edge
的weak_ptr
。
因此,要刪除Node
,請遍歷該節點的Edge
,然后將其刪除。 刪除所有Edge
之后,到Node
的所有shared_ptr
都超出范圍,並且該節點被銷毀。
如果這不切實際,那么重新設計的方法就不那么激烈了:
為每個Edge
分配某種唯一的標識符。 一個簡單的遞增計數器就可以了,並且有可能在Edge
的構造函數中自動進行處理。
使用其唯一標識符引用所有Edge
,而不是Edge
的shared_ptr
的std::set
,而是用標識符的std::map
替換為Edge
的shared_ptr
。 當銷毀特定的Node
時,從每個Node
移除每個Edge
變得很簡單。
除了實現離散標識符之外,還需要格外小心地使用指向Edge
的原始指針,並將std::less<Edge *>
作為其嚴格的弱排序比較器,作為每個邊緣的即興唯一標識符。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.