如何解决STL make_heap,pop_heap的自定义比较功能,如何使其在图形搜索例程中工作?
我的意图是使用堆作为承载尚未遍历的节点的数据结构,实现Prim的算法以查找无向图的最小生成树。
我设置了两个类Edge
和Node
,以便Graph
是list<Node>
,而Node
是list<Edge>
:
class Edge
{
public:
Edge();
Edge(int,int,int);
std::array<int,2> getNodes() const;
int getCost() const;
bool operator==(const Edge&) const;
bool operator!=(const Edge&) const;
private:
int node1,node2; // nodes are just indices of the nodes in the graph
int cost;
};
和
class Node
{
public:
Node();
Node(const Edge edg);
int getLabel() const;
inline std::list<Edge>::iterator begin() {return edges.begin();}
inline std::list<Edge>::iterator end() {return edges.end();}
std::list<Edge>::iterator erase(int);
bool operator==(Node&) const;
bool operator!=(Node&) const;
private:
int label;
std::list<Edge> edges;
};
我在下面的Prim例程中使用make_heap
和pop_heap
,但是我的实现无法正常工作。
我想这是由于堆例程中比较函数的实现不正确。
我使用的繁琐的比较功能由嵌套的lambda组成,因为需要识别图中具有交叉边缘且已遍历节点集的节点:
void heapPrim(Graph& graph) // imported graph,all nodes inside
{
list<Node> X(1,graph[0]); // X hosts the traversed nodes
vector<Node> unexplored_nodes( graph.begin(),graph.end() );
// take away first traversed node from unexplored_nodes
remove_if(unexplored_nodes.begin(),unexplored_nodes.end(),[X](const Node& a) mutable {return a == X.front();});
unexplored_nodes.pop_back();
// here lays the problem
make_heap(unexplored_nodes.begin(),[X](Node& a,Node& b) mutable ->bool {
int temp_score_a(INFTY),temp_score_b(INFTY); // INFTY: costant = 10^8
// comparison function applies only to nodes with crossing edges to X
for (list<Node>::iterator iter = X.begin(); iter != X.end(); ++iter)
{
list<Edge>::iterator find_a = find_if((*iter).begin(),(*iter).end(),[a](Edge& i){return i.getNodes()[1] == a.getLabel();});
if ( find_a != (*iter).end() )
temp_score_a = min( temp_score_a,(*find_a).getCost() );
list<Edge>::iterator find_b = find_if((*iter).begin(),[b](Edge& i){return i.getNodes()[1] == b.getLabel();});
if ( find_b != (*iter).end() )
temp_score_b = min( temp_score_b,(*find_b).getCost() );
};
return temp_score_a > temp_score_b;
});
// main loop finds all MST nodes
while ( X.size() != graph.size() ) {
list<Edge>::iterator iter_min_edge = X.back().begin();
X.push_back( unexplored_nodes.front() );
// same compare lambda function as 'make_heap' above
pop_heap(unexplored_nodes.begin(),temp_score_b(INFTY);
for (list<Node>::iterator iter = X.begin(); iter != X.end(); ++iter)
{
list<Edge>::iterator find_a = find_if((*iter).begin(),[a](Edge& i){return i.getNodes()[1] == a.getLabel();});
if ( find_a != (*iter).end() )
temp_score_a = min( temp_score_a,(*find_a).getCost() );
list<Edge>::iterator find_b = find_if((*iter).begin(),[b](Edge& i){return i.getNodes()[1] == b.getLabel();});
if ( find_b != (*iter).end() )
temp_score_b = min( temp_score_b,(*find_b).getCost() );
};
return temp_score_a > temp_score_b;
});
unexplored_nodes.pop_back();
}
cout << "evolution of new nodes X: ";
for (list<Node>::iterator iter = X.begin(); iter != X.end(); ++iter)
cout << (*iter).getLabel() << "; ";
cout << endl;
}
此实现会导致错误的结果,即在MST中选择了次优Node
。
我的问题:如何为不对所有范围的min
求值,而仅在具有交叉边缘的Node
中进行选择的堆实现比较功能?顺便说一下,这种解决方案是否有可能进行编码?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。