Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions pretext/Graphs/DijkstrasAlgorithm.ptx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,49 @@ def dijkstra(aGraph,start):
pq.decreaseKey(nextVert,newDist)
</code></program>
</listing>

<listing xml:id="graphs_lst-shortpath2">
<title>Dijkstra's Algorithm C++</title>
<program language="c++" label="graphs_lst-shortpath-prog2"><code><![CDATA[
#include "Graph.h"
#include <iostream>
using namespace std;

vector<Node> dijkstra(const vector<vector<Node>>&amp; graph, int start) {
vector<Node> distances;
for (int i = 0; i &lt; 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 &gt; distances[vertex].getKey()) {
continue;
}

for (int i = 0; i &lt; graph[vertex].size(); i++) {
Node neighbor = graph[vertex][i];

int newDistance = distance + neighbor.getKey();

if (newDistance &lt; distances[neighbor.getValue()].getKey()) {
distances[neighbor.getValue()] = Node(newDistance, vertex);
pq.insert(newDistance, neighbor.getValue());
}
}
cout &lt;&lt; "" &lt;&lt; endl;
}
return distances;
}
]]></code></program>
</listing>
<p>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
Expand Down
40 changes: 40 additions & 0 deletions pretext/Graphs/ImplementingKnightsTour.ptx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,46 @@ def knightTour(n,path,u,limit):
else:
done = True
return done</pre>

<listing xml:id="graphs_lst-knights-tour">
<title>Knight's Tour Analysis C++</title>
<program language="c++" label="graphs_lst-knights-tour"><code><![CDATA[
bool knightTour(int stepCount, int currentVertex,
vector<int>& path, vector<bool>& visited,
Graph& ktGraph, int n) {
visited[currentVertex] = true;
path.push_back(currentVertex);

if (stepCount == n * n) {
return true; // tour complete (recursive base case)
}

vector<int> 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<int> runKnightTour(int start, Graph& ktGraph, int n){
vector<int> path;
vector<bool> visited(n*n, false);

if (knightTour(1, start, path, visited, ktGraph, n)){
return path; //if there's a successful tour
}
return {};
}
]]></code></program>
</listing>
<p>Let's look at a simple example of <c>knightTour</c> in action. You
can refer to the figures below to follow the steps of the search. For
this example we will assume that the call to the <c>getConnections</c>
Expand Down
84 changes: 84 additions & 0 deletions pretext/Graphs/PrimsSpanningTreeAlgorithm.ptx
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,90 @@ def prim(G,start):

</code></program>
</listing>

<listing xml:id="2nd-prims">
<title>Prim's algorithm C++ Implementation</title>
<program language="c++" label="2nd-prims-cpp"><code><![CDATA[
#include <iostream>
#include <vector>
#include <queue>
#include <climits>
#include <unordered_map>
#include <set>
#include "prim.h"
using namespace std;


int prims(const unordered_map<int, vector<Edge>>& graph, int start){
set<int> notAdded; //S: nodes not yet in tree
set<int> inTree; //T: nodes in MST
vector<pair<int, int>> treeEdges; //edges that form MST

unordered_map<int, int> minCost; //minimum cost to connect each node in MST
unordered_map<int, int> 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<Node, vector<Node>, 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;
}
]]></code></program>
</listing>

<p>The following sequence of figures (<xref ref="fig-mst1"/> through <xref ref="fig-mst1"/>) shows the algorithm in operation on our sample
tree. We begin with the starting vertex as A. The distances to all the
other vertices are initialized to infinity. Looking at the neighbors of
Expand Down