How to free memory from minHeap C++ - c++

I have an implementation of Dijkstra's algorithm from https://www.geeksforgeeks.org/dijkstras-algorithm-for-adjacency-list-representation-greedy-algo-8/ but there is significant memory leaks when I try to use it. The problem is with the minHeap according to when I run it with valgrind. I have tried freeing each pointer like:
for (int i=0; i<size; i+=1){
free(minHeap->array[i]);
}
but valgrind gives invalid free() and the leak is not solved. Here is the Dijkstra's code.
// C++ program for Dijkstra's shortest path algorithm for adjacency
// list representation of graph
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <float.h>
// A structure to represent a node in adjacency list
struct AdjListNode
{
int dest;
double weight;
struct AdjListNode* next;
};
// A structure to represent an adjacency list
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, double 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, double 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 beginning
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;
double 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, double 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, double 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* const graph, vector<double> &dist, vector<double> const &max, vector<double> const &P_s, const int src){
int size = graph->V;
// minHeap represents set E
struct MinHeap* minHeap = createMinHeap(size);
// Initialize min heap with all vertices. dist value of all vertices
for (int v = 0; v < size; ++v)
{
// Testing different initialization
dist[v] = max[v];
// Make dist value of src vertex as 0 so that it is extracted first
if (v==src){
dist[v] = 0;
}
minHeap->array[v] = newMinHeapNode(v, dist[v]);
minHeap->pos[v] = v;
}
decreaseKey(minHeap, src, dist[src]);
// Initially size of min heap is equal to size
minHeap->size = size;
// 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] != DBL_MAX &&
(pCrawl->weight)/P_s[v] + dist[u] < dist[v])
{
dist[v] = dist[u] + pCrawl->weight/P_s[v];
// update distance value in min heap also
decreaseKey(minHeap, v, dist[v]);
}
pCrawl = pCrawl->next;
}
}
free(minHeap->pos);
free(minHeap->array);
free(minHeap);
}

I agree with the previous comments, this code is pure C, it should not be tagged as C++. Writing it in C++ would make it quite easier to read and to debug. Using std::vector would prevent your program from loosing any memory, because memory allocs are encapsulated in this dedicated class.
You may want to follow this tutorial about std::vector and object oriented programming : https://www.tutorialspoint.com/cplusplus/cpp_stl_tutorial.htm
Generally, new and delete (C++) are less error prone than malloc and free (C). They help to avoid some common mistakes (wrong size buffer allocation...)
Classes (C++) have initialisation (constructor) and destruction mechasism that helps to guarantee a valid state, they are a better alternative to C structures...

Related

Why is there a memory error in this adjacency list?

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;
}
}
}
}

List inside struct in c++

I have a list inside a struct in c++; I just want to insert elements to this list, as normal.
My structs are:
// A structure to represent an adjacency list node
struct AdjListNode
{
int dest;
int weight;
std::list<int> adjacents;
struct AdjListNode* next;
};
// A structure to represent an adjacency list
struct AdjList
{
int pos;
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;
};
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;
}
When I try to aceess:
graph->array[position].head->adjacents->push_back(number);
It just prompts this to me:
Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)
Sorry, I have no clue about this error.
The segmentation fault comes from
graph->array[position].head->adjacents.push_back(number);
with
graph->array[position].head = NULL;
I suppose that you have implicit struct invariant in your code since you have two lists that are likely to be connected: the linked list starting at AdjList::head and iterating through AdjNode::next and the list AdjNode::adjacent.
To keep the connection you can add a (C style) function that adds an element in both lists.
void
addAdjacent(AdjList& list, int adjacent) {
// struct AdjListNode* newNode = (struct AdjListNode*) malloc(sizeof(struct AdjListNode));
struct AdjListNode* newNode = new AdjListNode;
newNode->next = list.head;
list.head = newNode;
newNode->dest = 0;
newNode->weight = 0;
newNode->adjacents = std::list<int>(); // undefined behavior with malloc
newNode->adjacents.push_back(adjacent);
}
Note that it is a bad idea to mix C style (malloc/free) with C++ style (especially with the containers of the Standard Template Library). The commented part of my code creates a segmentation fault since a std::list has not its fields filled with 0.
At the end the following main function works even if it has many memory leaks (see the valgrind tool)
int main(int argc, char** argv) {
struct Graph* graph = createGraph(2);
addAdjacent(graph->array[0], 1);
addAdjacent(graph->array[1], 2);
free(graph);
return 0;
}
A C++-98 solution (without any memory leaks) could be:
// A structure to represent an adjacency list node
struct AdjListNode
{
int dest;
int weight;
std::list<int> adjacents;
struct AdjListNode* next;
AdjListNode() : dest(0), weight(0), next(NULL) {}
};
// A structure to represent an adjacency list
struct AdjList
{
int pos;
struct AdjListNode *head; // pointer to head node of list
// Initialize each adjacency list as empty by making head as NULL
AdjList() : pos(0), head(NULL) {}
~AdjList()
{ while (head) {
struct AdjListNode* temp = head;
head = head->next;
delete temp;
}
}
void addAdjacent(int adjacent)
{ struct AdjListNode* newNode = new AdjListNode;
newNode->next = head;
head = newNode;
newNode->adjacents.push_back(adjacent);
}
};
// 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;
// Create an array of adjacency lists. Size of array will be V
Graph(int v) : V(v), array(NULL)
{ if (v >= 0 && v <= 1000)
array = new struct AdjList[v];
else
throw std::bad_alloc();
}
~Graph()
{ delete [] array; }
};
int main() {
struct Graph* graph = new Graph(2);
graph->array[0].addAdjacent(1);
graph->array[1].addAdjacent(1);
delete graph;
return 0;
}

How to increase the maximum size of adjacent list in c++?

I am using the Dijkstra algorithm in this webpage. Recently I find out that if the number of the vertices exceeds 60000 in the graph, the system will respond with "core dumped" when adding new edge information as node into adjacent list.
Here is the excerpt of adjacent list in the original program:
// 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 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;
}
And here is the code of graph and adding new edge
// 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 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;
}
And for your reference, here is the main function that I test
int main()
{
int V = 100000;
struct Graph* graph = createGraph(V);
for(int i=0;i<V/2;i++)
for(int j=i+1;j<V;j++)
addEdge(graph, i, j, i+j);
return 0;
}
So you are trying to add almost 4*10^9 edges to the graph. Every edge (AdjListNode - object) needs 16 byte on a 64bit machine. We are also talking about at least 64GB, this is a lot.
However, every call of malloc(sizeof(struct AdjListNode)) costs more than just 16 byte: there are some overhead for managing the elements on the heap and the system concedes more than 16 byte with every request for memory. On my system I needed 2GB for 4*10^7 edges, i.e. ca. 50 byte per edge.
Anyway, you will be out of memory at some point of the program execution and malloc will return 0 in this part of your code:
struct AdjListNode* newAdjListNode(int dest, int weight)
{
struct AdjListNode* newNode =
(struct AdjListNode*) malloc(sizeof(struct AdjListNode));
//newNode is NULL if there is no memory!
newNode->dest = dest; //BOOM! segmentation error due to newNode==NULL
....
As you can see, the program will crash because of the NULL-pointer dereferencing.
I guess for every implementation, there is a limit of problem size for which it works. And the limit of this implementation is well bellow 4*10^9 edges.
As for your question: If you want to use less memory you should avoid allocating many different objects - it is better to put them into a continuous memory one after each other. For this std::vector is a good choice if you use C++ (but your code is pure C).

linker command failed with exit code 1 in g++ with -o3 flag

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

Creating an adjacency List for DFS

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;
}