I need to implement a breadth-first search and I am having trouble with the adjList (neighbor's list) for my vertex temp. First I find the vertex in my vertexList list then mark as visited and enqueue it. Then while the queue is not empty I check for all neighbors of the enqueued vertex: temp who are not visited, mark as visited and enqueue, and so on. But I don't know for what reason it says my adjList (neighbors list) is empty, which is not according to my display method when I actually print all vertices and its neighbors.
void testBreadthFirstSearch(string x)
{
vertex * s = findVertex(x);
list<vertex*> q;
s->visited = true;
s->predecessor = s;
q.push_back(s);
while (!q.empty()) {
vertex * temp = q.front();
q.pop_front();
for (list<vertex*>::iterator itr = temp->adjList.begin(); itr != temp->adjList.end(); itr++) {
if ((*itr)->visited == false) {
(*itr)->visited = true;
(*itr)->predecessor = s;
q.push_back(*itr);
}
}//end for
}//end while
Here is my graph and vertex class:
class directedGraph
{
private:
class vertex
{
public:
string data;
bool visited;
vertex * predecessor;
list<vertex*> adjList;
vertex(string x)
{
data = x;
visited = false;
}
};
list<vertex*> vertexList;
Related
I am trying to implement A* search algorithm with priority_queues and I have drawn the output on the console with opengl.
I got this output: Final path with A star
Where the cells in gray weren't visited, in yellow were visited and the final path in blue.
I think that the cells that were visited should be less and closer to the path, or I am wrong?
I computed the path with the following code:
list<Node*> compute_path_A_star(Node* start, Node* goal)
{
priority_queue< nodeDistance, vector< nodeDistance >, CompareDist> pq;
vector<Node*> came_from;
vector<float> cost_so_far;
nodeDistance first;
first.node = start;
first.distance = 0.0f;
pq.push(first);
came_from.resize(20 * 20, nullptr);
cost_so_far.resize(20 * 20, 9999.0f);
cost_so_far[start->x + 20 * start->y] = 0.0f;
//Compute where we came from for every location that’s visited
int i = 0;
while (!pq.empty())
{
nodeDistance temp = pq.top();
pq.pop();
Node* current_node = temp.node;
current_node = get_node(current_node->x, current_node->y);
if (current_node == goal) break;
for (auto n : current_node->neighbours)
{
float new_cost = cost_so_far[current_node->x + 20 * current_node->y] + n->cost;
if (new_cost < cost_so_far[n->x + 20 * n->y])
{
cost_so_far[n->x + 20 * n->y] = new_cost;
came_from[n->x + 20 * n->y] = current_node;
nodeDistance newNode;
newNode.node = n;
newNode.distance = new_cost + heuristic(n, goal);
pq.push(newNode);
}
}
}
#pragma region Create the path (start -> goal)
Node* current = new Node();
current = goal;
list<Node*> path;
path.push_back(current);
while (current != start)
{
current = came_from[current->x + 20 * current->y];
path.push_back(current);
}
path.reverse();
#pragma endregion
return path;
}
I used Manhattan distance for the heuristic:
float heuristic(Node* a, Node* b)
{
//Manhattan distance on a square grid
return (abs(a->x - b->x) + abs(a->y - b->y));
}
nodeDistance is a struct:
struct nodeDistance
{
Node* node;
float distance;
};
And for the comparision in the priority queue I defined this class:
class CompareDist
{
public:
bool operator()(nodeDistance& n1, nodeDistance& n2)
{
if (n1.distance > n2.distance)
return true;
else
return false;
}
};
I defined each node as:
struct Node
{
int x, y;
float cost;
Node* parent;
list<Node*> neighbours;
};
And the graph:
list<Node*> Graph;
Edit 1:
For the A star implementation, I was based on this page http://www.redblobgames.com/pathfinding/a-star/introduction.html.
There is something that I missed? Thanks!
Edit 2:
I have inserted some obstacles (dark-gray cells) and waypoints (pink cells) on the scene. In red the goal cell
In the code, I create an adjacency list with an array and each element of the array makes a list with it's adjacent nodes.
To access the array I needed to use ints; however, my vertex names were strings, so I mapped each vertex name to an int counting up from 0. As you can see in the nextNode() function the when a new node is created the'next'node should always be null.
An example result of the adjacency list will look something like this
inputVertices: a,b,c,d
inputEdges: (a,b), (a,d), (b,c) (d,b)
mapping: a<->0, b<->1, c<->2, d<->3
adjacency list:
arr elements| linked lists connected to elements
0 |->b->d
1 |->c
2 |
3 |->b
struct Node {
string vert;
int weight;
Node *next;
};
struct List {
struct Node *head;
};
class Graph {
int vertices;
int edges;
struct List *vertexArray;
int count = 0;
map<string, int> vertList;
public:
Graph(int vertices) {
this->vertices = vertices;
vertexArray = new List[vertices];
for (int i = 0; i < vertices; i++) {
vertexArray[i].head = NULL;
}
}
~Graph() {
vertList.clear();
}
Node *nextNode(string vert) {
Node *newNode = new Node;
newNode->vert = vert;
newNode->weight = 0;
newNode->next = NULL;
return newNode;
}
void addVertex(string vert) {
vertList[vert] = count; //maps Vertex to an integer in the order the Vertex is added
count++;
}
void addEdge(string head, string vert, int weight) {
Node *newNode = nextNode(vert);
newNode->weight = weight;
newNode->next = vertexArray[vertList.at(head)].head;
vertexArray[vertList.at(head)].head = newNode;
}
I stumbled upon my problem while trying to print my adjacency list
here and the program always crashes in the while loop below. It gets
through the first list of nodes fine, but crashes during the second
list.
I figured out the reason is the first list points to everything fine array[0].head->next = node1 node1->next = node2...noden->next = null(this exits the loop), however for the second list something different happens: array[1].head->next = node1 node1->next = node2...noden->next = 0xabababab. The last node should be null, but it is not. I set all new nodes to null. This causes a seg fault and crashes the program.
void print() {
for (int i = 0; i < vertices; i++) {
Node *n = vertexArray[i].head;
for (auto it = vertList.cbegin(); it != vertList.cend(); ++it) {
if ((*it).second == i) { // true if second type in map (aka int) == current array position
cout << (*it).first; //corresponding first type in map
while (n) {
cout << "-> " << n->vert;
n = n->next;
}
cout << endl;
}
}
}
}
I am using the code in this page. Recently I would like to compile with -o3 flag on my mac terminal. It turns out showing the error message, but the code can be successfully complied with -o flag without any errors.
Here are my code
// C / C++ program for Dijkstra's shortest path algorithm for adjacency
// list representation of graph
// C / C++ program for Dijkstra's shortest path algorithm for adjacency
// list representation of graph
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
// A structure to represent a node in adjacency list
struct AdjListNode
{
int dest;
int weight;
struct AdjListNode* next;
};
// A structure to represent an adjacency liat
struct AdjList
{
struct AdjListNode *head; // pointer to head node of list
};
// A structure to represent a graph. A graph is an array of adjacency lists.
// Size of array will be V (number of vertices in graph)
struct Graph
{
int V;
struct AdjList* array;
};
// A utility function to create a new adjacency list node
struct AdjListNode* newAdjListNode(int dest, int weight)
{
struct AdjListNode* newNode =
(struct AdjListNode*) malloc(sizeof(struct AdjListNode));
newNode->dest = dest;
newNode->weight = weight;
newNode->next = NULL;
return newNode;
}
// A utility function that creates a graph of V vertices
struct Graph* createGraph(int V)
{
struct Graph* graph = (struct Graph*) malloc(sizeof(struct Graph));
graph->V = V;
// Create an array of adjacency lists. Size of array will be V
graph->array = (struct AdjList*) malloc(V * sizeof(struct AdjList));
// Initialize each adjacency list as empty by making head as NULL
for (int i = 0; i < V; ++i)
graph->array[i].head = NULL;
return graph;
}
// Adds an edge to an undirected graph
void addEdge(struct Graph* graph, int src, int dest, int weight)
{
// Add an edge from src to dest. A new node is added to the adjacency
// list of src. The node is added at the begining
struct AdjListNode* newNode = newAdjListNode(dest, weight);
newNode->next = graph->array[src].head;
graph->array[src].head = newNode;
// Since graph is undirected, add an edge from dest to src also
newNode = newAdjListNode(src, weight);
newNode->next = graph->array[dest].head;
graph->array[dest].head = newNode;
}
// Structure to represent a min heap node
struct MinHeapNode
{
int v;
int dist;
};
// Structure to represent a min heap
struct MinHeap
{
int size; // Number of heap nodes present currently
int capacity; // Capacity of min heap
int *pos; // This is needed for decreaseKey()
struct MinHeapNode **array;
};
// A utility function to create a new Min Heap Node
struct MinHeapNode* newMinHeapNode(int v, int dist)
{
struct MinHeapNode* minHeapNode =
(struct MinHeapNode*) malloc(sizeof(struct MinHeapNode));
minHeapNode->v = v;
minHeapNode->dist = dist;
return minHeapNode;
}
// A utility function to create a Min Heap
struct MinHeap* createMinHeap(int capacity)
{
struct MinHeap* minHeap =
(struct MinHeap*) malloc(sizeof(struct MinHeap));
minHeap->pos = (int *)malloc(capacity * sizeof(int));
minHeap->size = 0;
minHeap->capacity = capacity;
minHeap->array =
(struct MinHeapNode**) malloc(capacity * sizeof(struct MinHeapNode*));
return minHeap;
}
// A utility function to swap two nodes of min heap. Needed for min heapify
void swapMinHeapNode(struct MinHeapNode** a, struct MinHeapNode** b)
{
struct MinHeapNode* t = *a;
*a = *b;
*b = t;
}
// A standard function to heapify at given idx
// This function also updates position of nodes when they are swapped.
// Position is needed for decreaseKey()
void minHeapify(struct MinHeap* minHeap, int idx)
{
int smallest, left, right;
smallest = idx;
left = 2 * idx + 1;
right = 2 * idx + 2;
if (left < minHeap->size &&
minHeap->array[left]->dist < minHeap->array[smallest]->dist )
smallest = left;
if (right < minHeap->size &&
minHeap->array[right]->dist < minHeap->array[smallest]->dist )
smallest = right;
if (smallest != idx)
{
// The nodes to be swapped in min heap
MinHeapNode *smallestNode = minHeap->array[smallest];
MinHeapNode *idxNode = minHeap->array[idx];
// Swap positions
minHeap->pos[smallestNode->v] = idx;
minHeap->pos[idxNode->v] = smallest;
// Swap nodes
swapMinHeapNode(&minHeap->array[smallest], &minHeap->array[idx]);
minHeapify(minHeap, smallest);
}
}
// A utility function to check if the given minHeap is ampty or not
int isEmpty(struct MinHeap* minHeap)
{
return minHeap->size == 0;
}
// Standard function to extract minimum node from heap
struct MinHeapNode* extractMin(struct MinHeap* minHeap)
{
if (isEmpty(minHeap))
return NULL;
// Store the root node
struct MinHeapNode* root = minHeap->array[0];
// Replace root node with last node
struct MinHeapNode* lastNode = minHeap->array[minHeap->size - 1];
minHeap->array[0] = lastNode;
// Update position of last node
minHeap->pos[root->v] = minHeap->size-1;
minHeap->pos[lastNode->v] = 0;
// Reduce heap size and heapify root
--minHeap->size;
minHeapify(minHeap, 0);
return root;
}
// Function to decreasy dist value of a given vertex v. This function
// uses pos[] of min heap to get the current index of node in min heap
void decreaseKey(struct MinHeap* minHeap, int v, int dist)
{
// Get the index of v in heap array
int i = minHeap->pos[v];
// Get the node and update its dist value
minHeap->array[i]->dist = dist;
// Travel up while the complete tree is not hepified.
// This is a O(Logn) loop
while (i && minHeap->array[i]->dist < minHeap->array[(i - 1) / 2]->dist)
{
// Swap this node with its parent
minHeap->pos[minHeap->array[i]->v] = (i-1)/2;
minHeap->pos[minHeap->array[(i-1)/2]->v] = i;
swapMinHeapNode(&minHeap->array[i], &minHeap->array[(i - 1) / 2]);
// move to parent index
i = (i - 1) / 2;
}
}
// A utility function to check if a given vertex
// 'v' is in min heap or not
bool isInMinHeap(struct MinHeap *minHeap, int v)
{
if (minHeap->pos[v] < minHeap->size)
return true;
return false;
}
// The main function that calulates distances of shortest paths from src to all
// vertices. It is a O(ELogV) function
void dijkstra(struct Graph* graph, int src)
{
int V = graph->V;// Get the number of vertices in graph
int dist[V]; // dist values used to pick minimum weight edge in cut
// minHeap represents set E
struct MinHeap* minHeap = createMinHeap(V);
// Initialize min heap with all vertices. dist value of all vertices
for (int v = 0; v < V; ++v)
{
dist[v] = INT_MAX;
minHeap->array[v] = newMinHeapNode(v, dist[v]);
minHeap->pos[v] = v;
}
// Make dist value of src vertex as 0 so that it is extracted first
minHeap->array[src] = newMinHeapNode(src, dist[src]);
minHeap->pos[src] = src;
dist[src] = 0;
decreaseKey(minHeap, src, dist[src]);
// Initially size of min heap is equal to V
minHeap->size = V;
// In the followin loop, min heap contains all nodes
// whose shortest distance is not yet finalized.
while (!isEmpty(minHeap))
{
// Extract the vertex with minimum distance value
struct MinHeapNode* minHeapNode = extractMin(minHeap);
int u = minHeapNode->v; // Store the extracted vertex number
// Traverse through all adjacent vertices of u (the extracted
// vertex) and update their distance values
struct AdjListNode* pCrawl = graph->array[u].head;
while (pCrawl != NULL)
{
int v = pCrawl->dest;
// If shortest distance to v is not finalized yet, and distance to v
// through u is less than its previously calculated distance
if (isInMinHeap(minHeap, v) && dist[u] != INT_MAX &&
pCrawl->weight + dist[u] < dist[v])
{
dist[v] = dist[u] + pCrawl->weight;
// update distance value in min heap also
decreaseKey(minHeap, v, dist[v]);
}
pCrawl = pCrawl->next;
}
}
free(minHeap->pos);
for (int i=0;i<minHeap->size;i++) {
free(minHeap->array[i]);
}
free(minHeap->array);
free(minHeap);
}
// Driver program to test above functions
int main()
{
// create the graph given in above fugure
int V = 20000,t=0;
while (t!=10) {
struct Graph* graph = createGraph(V);
for (int i=0; i<10000; i++) {
for(int j=10000;j<20000;j++){
addEdge(graph, 0, i, i);
addEdge(graph, i, j, i+j);
}
}
dijkstra(graph, 0);
for(int d=0; d<graph->V; d++)
{
AdjListNode *p1=graph->array[d].head, *p2;
while(p1)
{
p2=p1;
p1=p1->next;
free(p2);
}
}
free(graph->array);
free(graph);
t++;
}
return 0;
}
Here is the error message
seshunsakaitekiMacBook-Pro:test Daniel$ g++ -o3 TEST main.cpp
ld: can't link with a main executable file 'TEST' for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
The lowercase -o flag specifies the output file.
The uppercase -O flag specifies the optimization level.
You may have intended to use:
g++ -O3 -o TEST main.cpp
Instead of:
g++ -o3 TEST main.cpp
I've been working on a project for college and ran into a rather large problem. I'm supposed to make a function that gets the shortest path through a directed graph from point A to point B and display the path in order.
EX. if the node holds a state name and we want to find the shortest path between California and Utah the output would show california -> nevada -> utah
Currently, my traversal shows all nodes searched with bfs instead of the list of nodes that we took to get from point A to point B.
Below is my implementation of the assignment. My only real question is how would I go about keeping track of the nodes I actually traversed instead of all nodes searched.
bool DirectedGraph::GetShortestPath(
const string& startNode, const string& endNode,
bool nodeDataInsteadOfName, vector<string>& traversalList) const
{
//Nodes are the same
if (startNode.compare(endNode) == 0)
return false;
//Stores the location of our nodes in the node list
vector<int> path;
//Queue to hold the index of the node traversed
queue<int> q;
//Create our boolean table to handle visited nodes
bool *visited = new bool[m_nodes.size()];
//initialize bool table
memset(visited, false, sizeof(bool) * m_nodes.size());
//Label the start node as visited
visited[GetNodeIndex(startNode)] = true;
//Push the node onto our queue
q.push(GetNodeIndex(startNode));
while (!q.empty())
{
//Store the nodes index
int index = q.front();
path.push_back(q.front());
q.pop();
int i = 0;
for (i = 0; i < m_nodes[index]->Out.size(); i++)
{
//If this node matches what we are looking for break/return values
if (m_nodes[index]->Out[i]->targetI == GetNodeIndex(endNode))
{
path.push_back(m_nodes[index]->Out[i]->targetI);
if (nodeDataInsteadOfName)
{
path.push_back(m_nodes[index]->Out[i]->targetI);
for (int x = 0; x < path.size(); x++)
{
traversalList.push_back(m_nodes[path[x]]->Data);
}
}
else
{
for (int x = 0; x < path.size(); x++)
{
traversalList.push_back( m_nodes[path[x]]->Name);
}
}
return true;
}
//Continue through the data
if (!visited[m_nodes[index]->Out[i]->targetI])
{
visited[m_nodes[index]->Out[i]->targetI] = true;
q.push(m_nodes[index]->Out[i]->targetI);
}
}
}
// You must implement this function
return false;
}
//definition of graph private members
struct Edge
{
int srcI; // Index of source node
int targetI; // Index of target node
Edge(int sourceNodeIndex, int targetNodeIndex)
{
srcI = sourceNodeIndex;
targetI = targetNodeIndex;
}
};
struct Node
{
string Name;
string Data;
Node(const string& nodeName, const string& nodeData)
{
Name = nodeName;
Data = nodeData;
}
// List of incoming edges to this node
vector<Edge*> In;
// List of edges going out from this node
vector<Edge*> Out;
};
// We need a list of nodes and edges
vector<Node*> m_nodes;
vector<Edge*> m_edges;
// Used for efficiency purposes so that quick node lookups can be
// done based on node names. Maps a node name string to the index
// of the node within the nodes list (m_nodes).
unordered_map<string, int> m_nodeMap;
The first problem is with the if inside the for loop. Your path variable can only contain two items: the starting and the ending nodes. I suggest you do no track the path with the for loop. Instead, assign each node a distance.
struct Node
{
string Name;
string Data;
int Distance;
Node(const string& nodeName, const string& nodeData)
{
Name = nodeName;
Data = nodeData;
Distance = INT_MAX;
}
// List of incoming edges to this node
vector<Edge*> In;
// List of edges going out from this node
vector<Edge*> Out;
};
and set the distance of the starting node to zero, before looping.
m_nodes[GetNodeIndex(startNode)]->Distance = 0;
At each iteration, pick a node from the queue (you called it index), loop through its adjacency list (outgoing arcs) and test if the adjacent node is visited. If the node is visited, skip it. If the node is not visited, visit it by setting its distance to
m_nodes[index]->Distance + 1
After updating the distance of each node, check if it is the final node, if so break out of the loops.
At this point you have the distance's updated properly. Work your way from the end node backwards, each time selecting the node from the adjacency list with (distance = current node's distance - 1). You can do this using m_edges vector, each time you actually know targetI, so you can check for its corresponding scrI's with the distance value mentioned above.
I'm having trouble creating a Depth First Search for my program. So far I have a class of edges and a class of regions. I want to store all the connected edges inside one node of my region. I can tell if something is connected by the getKey() function I have already implemented. If two edges have the same key, then they are connected. For the next region, I want to store another set of connected edges inside that region, etc etc. However, I am not fully understanding DFS and I'm having some trouble implementing it. I'm not sure when/where to call DFS again. Any help would be appreciated!
class edge
{
private:
int source, destination, length;
int key;
edge *next;
public:
getKey(){ return key; }
}
class region
{
edge *data;
edge *next;
region() { data = new edge(); next = NULL; }
};
void runDFS(int i, edge **edge, int a)
{
region *head = new region();
aa[i]->visited == true;//mark the first vertex as true
for(int v = 0; v < a; v++)
{
if(tem->edge[i].getKey() == tem->edge[v].getKey()) //if the edges of the vertex have the same root
{
if(head->data == NULL)
{
head->data = aa[i];
head->data->next == NULL;
} //create an edge
if(head->data)
{
head->data->next = aa[i];
head->data->next->next == NULL;
}//if there is already a node connected to ti
}
if(aa[v]->visited == false)
runDFS(v, edge, a); //call the DFS again
} //for loop
}
assuming n is total number of edges, k is final number of regions.
Creating adjacency list for the requisite DFS might be too costly O(n^2) (if k=1 i.e. all edges belong to same region) and hence dfs will cost you O(V+E) i.e. O(n^2) in the worst case.
Otherwise problem is easily solvable in O(n * log(k)) as follows:
Traverse through all edges adding them to the head of corresponding regions (using balanced bst eg. stl-map) [you may use hashing for this too]
traverse through all the regions and connect them in requisite linear fashion
No guaranteed O(n) solution exists for the problem I guess..
I tried to implement a adjacency list creating function.The next pointer of adj_list struct takes you down the adjacency list(there is no relationship between 2 nodes connected by next) and the list pointer is the adjacency list. The node has the address of the adj_list which has its adjacency list.
struct node{
int id;
adj_list* adj;
};
struct adj_list{
adj_list* next;
adj_list* list;
node* n;
adj_list(node& _n){
n = &(_n);
next = NULL;
list = NULL;
}
};
node* add_node(int id,std::queue<int> q , node* root)
{
node* n = new node(id);
adj_list* adj = new adj_list(*n);
n->adj = adj;
if(root == NULL){
return n;
}
std::queue<adj_list*> q1;
while(1){
adj_list* iter = root->adj;
if(q.empty())break;
int k = q.front();
q.pop();
while(iter){
if(iter->n->id == k){
q1.push(iter);
adj_list* temp = iter->list;
iter->list = new adj_list(*n);
break;
}
iter = iter->next;
}
}
adj_list* iter = root->adj;
while(iter->next){
iter = iter->next;
}
iter->next = adj;
while(!q1.empty()){
adj_list* temp = q1.front();
q1.pop();
adj->list = temp;
adj = temp;
}
return root;
}