diff --git a/pretext/Graphs/DijkstrasAlgorithm.ptx b/pretext/Graphs/DijkstrasAlgorithm.ptx index 67c997ef..d1221d41 100755 --- a/pretext/Graphs/DijkstrasAlgorithm.ptx +++ b/pretext/Graphs/DijkstrasAlgorithm.ptx @@ -41,6 +41,49 @@ def dijkstra(aGraph,start): pq.decreaseKey(nextVert,newDist) + +
+using namespace std;
+
+vector dijkstra(const vector>& graph, int start) {
+ vector distances;
+ for (int i = 0; i < graph.size(); i++) {
+ distances.push_back(Node(INF, -1));
+ }
+ distances[start] = Node(0, start);
+
+ BinHeapMap pq;
+ pq.insert(0, start);
+
+ while (!pq.isEmpty()) {
+ Node current = pq.delMin();
+ int distance = current.getKey();
+ int vertex = current.getValue();
+
+ if (distance > distances[vertex].getKey()) {
+ continue;
+ }
+
+ for (int i = 0; i < graph[vertex].size(); i++) {
+ Node neighbor = graph[vertex][i];
+
+ int newDistance = distance + neighbor.getKey();
+
+ if (newDistance < distances[neighbor.getValue()].getKey()) {
+ distances[neighbor.getValue()] = Node(newDistance, vertex);
+ pq.insert(newDistance, neighbor.getValue());
+ }
+ }
+ cout << "" << endl;
+ }
+ return distances;
+}
+ ]]> Dijkstra's algorithm uses a priority queue. You may recall that a priority queue is based on the heap that we implemented in the Tree Chapter. There are a couple of differences between that diff --git a/pretext/Graphs/ImplementingKnightsTour.ptx b/pretext/Graphs/ImplementingKnightsTour.ptx index 0ce14e10..ada21c57 100644 --- a/pretext/Graphs/ImplementingKnightsTour.ptx +++ b/pretext/Graphs/ImplementingKnightsTour.ptx @@ -57,6 +57,46 @@ def knightTour(n,path,u,limit): else: done = True return done + +
& path, vector& visited,
+ Graph& ktGraph, int n) {
+ visited[currentVertex] = true;
+ path.push_back(currentVertex);
+
+ if (stepCount == n * n) {
+ return true; // tour complete (recursive base case)
+ }
+
+ vector nbrs = ktGraph.getVertex(currentVertex)->getConnections();
+ for (int nbr : nbrs) {
+ if (!visited[nbr]) {
+ if (knightTour(stepCount + 1, nbr, path, visited, ktGraph, n)) {
+ return true;
+ }
+ }
+ }
+
+ // backtrack
+ visited[currentVertex] = false;
+ path.pop_back();
+ return false;
+}
+
+vector runKnightTour(int start, Graph& ktGraph, int n){
+ vector path;
+ vector visited(n*n, false);
+
+ if (knightTour(1, start, path, visited, ktGraph, n)){
+ return path; //if there's a successful tour
+ }
+ return {};
+}
+ ]]> Let's look at a simple example of
+#include
+#include
+#include
+#include
+#include
+#include "prim.h"
+using namespace std;
+
+
+int prims(const unordered_map>& graph, int start){
+ set notAdded; //S: nodes not yet in tree
+ set inTree; //T: nodes in MST
+ vector> treeEdges; //edges that form MST
+
+ unordered_map minCost; //minimum cost to connect each node in MST
+ unordered_map parent;
+
+ for (auto& v : graph) {
+ notAdded.insert(v.first);
+ minCost[v.first] = INT_MAX; //minimum cost is set to inf
+ parent[v.first] = -1; //the initial vertex has no parents
+ }
+
+ minCost[start] = 0; //starting vertex has no cost
+
+ //pq to select next node with the smallest edge
+ priority_queue, compareWeight> pq;
+ pq.push({start, 0});
+
+ cout<< "Prims starting at node "<< start << "\n\n";
+
+ while (!pq.empty()){ //continue looping until MST is complete
+ Node currentNode = pq.top(); //node with the smallest weight
+ pq.pop(); //remove it from the pq
+ int n = currentNode.vertex; //vertext to be processe
+
+ if(notAdded.find(n) == notAdded.end()) continue; //skip if processed
+
+ //move from S to T
+ notAdded.erase(n);
+ inTree.insert(n); //add to list of nodes in MST
+
+ //add the connecting edge if not the starting vertex
+ if (parent[n] != -1){
+ treeEdges.push_back({parent[n], n});
+ }
+
+ cout << "Added vertex " << n << " to MST\n";
+ cout << "Current MST edges: ";
+ for (auto& e : treeEdges) cout << "(" << e.first << "," << e.second << ") ";
+ cout << "\n";
+
+ // Explore all neighbors of u
+ for (auto& edge : graph.at(n)) {
+ int v = edge.pointsTo; //neighbor of vertex
+ int weight = edge.weight;
+
+ // Only consider vertices not in MST yet
+ if (notAdded.find(v) != notAdded.end() && weight < minCost[v]) {
+ minCost[v] = weight;
+ parent[v] = n;
+ pq.push({v, weight}); //push v and the weight to pq
+ }
+ }
+ }
+
+ int totalWeight = 0;
+ cout << "\nFinal Minimum Spanning Tree:\n";
+ for (auto& e : treeEdges) { //go through every edge pair (parent, child)
+ int w = minCost[e.second];
+ totalWeight += w;
+ cout << e.first << " - " << e.second << " (weight " << w << ")\n";
+ }
+
+ return totalWeight;
+}
+ ]]> The following sequence of figures (