私はバイナリイメージでパスを見つけるために、ある時間前にDijkstraを実装しています。私は、のベクトルを含む構造体GraphNodes
のベクトルとしてグラフを表しました。このベクトルは、ノードの他のノードへのすべての接続を含んでいました。各接続には、エッジの重みであるdistance属性があります。ここで私が使用される二つの構造体は、以下のとおりです。
//forward declaration
struct GraphNode;
struct Connection {
Connection() : distance(1) { };
Connection(GraphNode* ptr, double distance) : ptr(ptr), distance(distance) { };
bool operator==(const Connection &other) const;
GraphNode* ptr;
double distance;
};
struct GraphNode {
GraphNode() : connections(8), predecessor(NULL), distance(-1) { };
cv::Point point;
double distance;
GraphNode* predecessor;
std::vector<Connection> connections;
};
bool Connection::operator==(const Connection &other) const {
return ptr == other.ptr && distance == other.distance;
}
GraphNode
の距離属性は、それが現在ダイクストラアルゴリズムであり、距離なので、開始ノードまでの最短現在知られている距離の距離。最初は-1
で初期化されています。
私は、このようにダイクストラアルゴリズムを実装:あなたは、これまで使用していないすべてのノードを含むセットunusedNodes
がある見たよう
std::vector<cv::Point> findShortestPathDijkstra(std::vector<GraphNode>& graph, int startNodeIndex, int destNodeIndex) const {
GraphDistanceSorter sorter(graph);
std::set<GraphNode*, GraphDistanceSorter> unusedNodes(sorter);
for (int i = 0; i < graph.size(); ++i) {
unusedNodes.insert(&graph[i]);
}
while (unusedNodes.size() > 0) {
GraphNode* currentNode = *unusedNodes.begin();
if (currentNode->distance == -1) {
return std::vector<cv::Point>();
}
if (currentNode == &graph[destNodeIndex]) break;
unusedNodes.erase(currentNode);
//update distances of connected nodes
for (Connection const& con : currentNode->connections) {
/*here we could check if the element is really in unusedNodes (search, O(log n)), but this would
actually take longer than calculating the new distance (O(1)), which will in this case always be greater
than the old one, so the distance is never updated for nodes not in unusedNodes()*/
double newDistance = currentNode->distance + con.distance;
if (newDistance < con.ptr->distance || con.ptr->distance == -1) {
unusedNodes.erase(con.ptr);
con.ptr->distance = newDistance;
con.ptr->predecessor = currentNode;
unusedNodes.insert(con.ptr);
}
}
}
//now trace back the path as a list of points
std::vector<cv::Point> points;
GraphNode* current = &graph[destNodeIndex];
points.push_back(current->point);
while (current != &graph[startNodeIndex]) {
if (current->predecessor == NULL) return std::vector<cv::Point>();
current = current->predecessor;
points.push_back(current->point);
}
return points;
}
。 graphNodes上のポインタのみを含んでいます。実際のグラフ表示はベクトル内にあります。セットを持つ利点は、それが常に特定の基準に従ってソートされることです。私は自分のソーターGraphDistanceSorter
を実装して、Dijkstraアルゴリズムの距離基準に従ってGraphNodesをソートしました。私はちょうどセットから最初のノードを選択し、それが最小の距離を持つ一つだということを知っている必要があり、この方法:
struct GraphDistanceSorter {
bool operator() (const GraphNode* lhs, const GraphNode* rhs) const;
};
bool GraphDistanceSorter::operator() (const GraphNode* lhs, const GraphNode* rhs) const {
if (lhs->distance == rhs->distance) {
return lhs < rhs;
} else {
if (lhs->distance != -1 && rhs->distance != -1) {
if (lhs->distance != rhs->distance) {
return lhs->distance < rhs->distance;
}
} else if (lhs->distance != -1 && rhs->distance == -1) {
return true;
}
return false;
}
}
あなたが代わりに3つのintの 'のstd :: tuple'sを使用して検討する必要があります:終わりに私は隣接リストを使用してグラフのdiffreent変種のいつもの実装(リストとしてベクトル)であなたを残します ネストされたペアのうち、しかし、私はあなたが世界で最高のものではないにしても理解する解決策に行くと言うでしょう。後でもっと経験を積んだら、いつでも改善することができます。 – Hiura
グラフを接続リストとして保存する方法ペアのベクトル? 1対は1つの接続を表す。 3 - > 4,5 - > 3、... – user1488118
はい、それぞれのペア/エッジにはウェイトがあります – Mateusz