I am using the Dijkstra Algorithm with Adjacency List in this webpage. Since I want to build up different graphs and compute shortest paths many times, I add some "free" command to free the memory. However, the memory usage still increase after many iterations
Here are my modified code:
// 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 = 10000,t=0;
while (t!=10) {
struct Graph* graph = createGraph(V);
for (int i=0; i<5000; i++) {
for(int j=5000;j<10000;j++){
addEdge(graph, 0, i, i);
addEdge(graph, i, j, i+j);
}
}
dijkstra(graph, 0);
free(graph->array);
free(graph);
t++;
}
return 0;
}
You have these three lines at the end of your main:
free(graph->array);
free(graph);
t++;
You need to free the elements of the array (the adjacency lists) before freeing the array. Add this loop before the three lines:
for(int d=0; d<graph->V; d++)
{
AdjListNode *p1=graph->array[d].head, *p2;
while(p1)
{
p2=p1;
p1=p1->next;
free(p2);
}
}
Related
so I have this function which does a depth first search traversal of a graph and prints out the nodes traversed. But instead of printing the nodes I want this function to return the node it newly moved to, return one node per call of the function.
when I call the function with the start node 0, it should return the next node in traversal (order of the nodes when traversing is printed out when running the program, along with the graph's adjacency list), which is 1 but it is returning 3.
the traversal order is: 1 2 3 2 4 5 4 6
below is what I have tried:
int DFS(struct Graph* graph, int vertex) {
struct node* adjList = graph->adjLists[vertex];
struct node* temp = adjList;
int back = 0;
graph->visited[vertex] = 1;
while (temp != NULL) {
int connectedVertex = temp->vertex;
if (graph->visited[connectedVertex] == 0) {
if ( back==1 ) {
return vertex;
printf("node: %d\n", vertex);
}
printf("node 1: %d\n", connectedVertex);
return DFS(graph, connectedVertex);
back = 1;
}
temp = temp->next;
}
return vertex;
}
and here is the function without the return statements (originally a void function):
void DFS(struct Graph* graph, int vertex) {
struct node* adjList = graph->adjLists[vertex];
struct node* temp = adjList;
int back = 0; // = "We have already expanded vertex"
graph->visited[vertex] = 1;
while (temp != NULL) {
int connectedVertex = temp->vertex;
if (graph->visited[connectedVertex] == 0) {
if ( back==1 ) // Report the revisited node
printf("node: %d\n", vertex);
printf("node: %d\n", connectedVertex);
DFS(graph, connectedVertex);
back = 1; // Tag this node as having been expanded.
}
temp = temp->next;
}
}
and here is my full program:
// DFS algorithm in C
#include <stdio.h>
#include <stdlib.h>
struct node {
int vertex;
struct node* next;
};
struct node* createNode(int v);
struct Graph {
int numVertices;
int* visited;
struct node** adjLists;
};
void DFS(struct Graph* graph, int vertex) {
struct node* adjList = graph->adjLists[vertex];
struct node* temp = adjList;
int back = 0; // = "We have already expanded vertex"
graph->visited[vertex] = 1;
while (temp != NULL) {
int connectedVertex = temp->vertex;
if (graph->visited[connectedVertex] == 0) {
if ( back==1 ) // Report the revisited node
printf("node: %d\n", vertex);
printf("node: %d\n", connectedVertex);
DFS(graph, connectedVertex);
back = 1; // Tag this node as having been expanded.
}
temp = temp->next;
}
}
// Create a node
struct node* createNode(int v) {
struct node* newNode = malloc(sizeof(struct node));
newNode->vertex = v;
newNode->next = NULL;
return newNode;
}
// Create graph
struct Graph* createGraph(int vertices) {
struct Graph* graph = malloc(sizeof(struct Graph));
graph->numVertices = vertices;
graph->adjLists = malloc(vertices * sizeof(struct node*));
graph->visited = malloc(vertices * sizeof(int));
int i;
for (i = 0; i < vertices; i++) {
graph->adjLists[i] = NULL;
graph->visited[i] = 0;
}
return graph;
}
void sortedInsert(struct node** head_ref,
struct node* new_node)
{
struct node* current;
/* Special case for the head end */
if (*head_ref == NULL
|| (*head_ref)->vertex
>= new_node->vertex) {
new_node->next = *head_ref;
*head_ref = new_node;
}
else {
/* Locate the node before
the point of insertion */
current = *head_ref;
while (current->next != NULL
&& current->next->vertex < new_node->vertex) {
current = current->next;
}
new_node->next = current->next;
current->next = new_node;
}
}
// Add edge
void addEdge(struct Graph* graph, int src, int dest) {
// Add edge from src to dest
sortedInsert(&graph->adjLists[src], createNode(dest));
// Add edge from dest to src
sortedInsert(&graph->adjLists[dest], createNode(src));
}
// Print the graph
void printGraph(struct Graph* graph) {
int v;
for (v = 0; v < graph->numVertices; v++) {
struct node* temp = graph->adjLists[v];
printf("\n Adjacency list of vertex %d\n ", v);
while (temp) {
printf("%d -> ", temp->vertex);
temp = temp->next;
}
printf("\n");
}
}
int main() {
struct Graph* graph = createGraph(7);
addEdge(graph, 0, 1);
addEdge(graph, 0, 3);
addEdge(graph, 1, 2);
addEdge(graph, 2, 3);
addEdge(graph, 2, 4);
addEdge(graph, 4, 5);
addEdge(graph, 4, 6);
printGraph(graph);
DFS(graph, 0);
return 0;
}
Help would be much appreciated.
" I want this function to return the node it newly moved to, return one node per call of the function."
This is a bad idea, because your function is recursive.
To get the nodes traversed in order add the visited node index to a global data structure.
Note: Recursion is the correct way to go here. Returning the node visited from the recursive function will not work.
Allow me to describe how I would do this:
When searching through graphs, the concept of a "visitor" is useful. A visitor is a function that the search code calls each time it reaches a new node. It makes writing the search code slightly more complex, but you need only do it once. Once written you can adapt the algorithm to do different purposes without disturbing your carefully tested and optimized search code. In this case, all the visitor need do is record the node indexes as they are visited.
Note that once you have the visitor written, you can easily change the searching algorithm ( say from depth first to breadth first ) without writing new code.
Your visitor can look like this in C++
/// in global namespace
std::vector<int> gvIndexNodeVisitedOrder();
void visitor( int indexNode )
{
gvIndexNodeVositedOrder.push_back( indexNode );
}
The searching code looks like:
void depthFirstRecurse(
int v )
{
// Call the visitor
visitor(v);
// remember this node has been visited
gvNodeVisited[v] = 1;
// look at adjacent nodes
for (int w : adjacent(v)) {
// check node has not been visited
if (!gvNodeVisited[w])
{
// continue search from new node
depthFirstRecurse(w);
}
}
}
Note: I have placed stuff in the global namespace because the original question is tagged C. In reality I would use a C++ class and make the "globals" private attributes and methods of the class.
I added this two fuctions:
// Adds a node to a list of nodes
void addNode(struct node** nodeList, int vertex){
struct node *temp = *nodeList;
if(*nodeList == NULL){
*nodeList = createNode(vertex);
}else{
while(temp->next != NULL){
temp = temp->next;
}
temp->next = createNode(vertex);
}
}
// Prints a list of nodes
void printNodeList(struct node* nodeList) {
struct node* temp = nodeList;
while(temp != NULL){
printf("%d", temp->vertex);
if(temp->next != NULL){
printf(" -> ");
}
temp = temp->next;
}
printf("\n");
}
and modified DFS and main as follow:
// added last argument
void DFS(struct Graph* graph, int vertex, struct node** nodeList) {
struct node* adjList = graph->adjLists[vertex];
struct node* temp = adjList;
graph->visited[vertex] = 1;
addNode(nodeList, vertex); // added this
while (temp != NULL) {
int connectedVertex = temp->vertex;
if (graph->visited[connectedVertex] == 0) {
printf("node: %d\n", connectedVertex);
DFS(graph, connectedVertex, nodeList);
addNode(nodeList, vertex); // added this
}
temp = temp->next;
}
}
int main() {
struct node* nodeList = NULL;
struct Graph* graph = createGraph(7);
addEdge(graph, 0, 1);
addEdge(graph, 0, 3);
addEdge(graph, 1, 2);
addEdge(graph, 2, 3);
addEdge(graph, 2, 4);
addEdge(graph, 4, 5);
addEdge(graph, 4, 6);
printGraph(graph);
DFS(graph, 0, &nodeList);
printNodeList(nodeList);
return 0;
}
If I would have to define the traversal order of the nodes, in your example graph it would not be 1 -> 2 -> 3 -> 2 -> 4 -> 5 -> 4 -> 6 but rather 0 -> 1 -> 2 -> 3 -> 2 -> 4 -> 5 -> 4 -> 6 -> 4 -> 2 -> 1 -> 0, since I think that any time you "land" on a different node (either because you call DFS or because DFS gives back control to the caller), that "counts" in the path you're following to search the graph, and this until you're back to the main function, hence you've finished searching. Therefore in the DFS function above I implemented that, but if you need the order you mentioned, just add addNode(nodeList, vertex); below your printf statements and you should get it.
Since the function is recursive you can't really use the return statement to return the visited nodes, because what you want to have at the end is a list of elements and not just a single value. For instance in your code you defined the return type of DFS as int, this means that the function can only give you back a number, but when you call DFS in your main function you expect it to give you back a list of node that got visited. You may be able to figure out something returning a pointer to a data structure or maybe returning an int (the visited vertex) and calling something like addNode(list, DFS(g, vertex)) but you would still need to pass the list to DFS (otherwise you won't be able to call addNode(list,...) inside of it), so you would get addNode(list, DFS(g, vertex, list)), therefore I don't think you would get any advantage out of it, but I don't know.
What I did is to define a list in the main function and to pass it to the recursive function (does not need to return anything), which is then able to add the visited node to it when necessary. The first call to addNode(nodeList, vertex) happens only once per vertex since you never call DFS more than one time for any vertex, while the second happens every time you come back to a vertex after having searched into one of it's neighbors.
Can you please modify my code to be able to fulfill the following requirements:
-Instead of passing numbers in the struct, we first need to pass processes and resources. For e.g P1,P2,P3,R1,R2...
-Then the pointer should be as such: PA->RS, PB->RT, PC->RS, PD->RS, PD->RT, PE->RV, PF->RS, PG->RU, RG->PA, RU->PD, RT->PE, RW->PF, RV->PG
-Our program should find a cycle by considering the adjency list. If 2 nodes are repeated in the adjency list, it means that there is a cycle and hence the system is deadlocked and a message should be outputted. For now, i just want to hardcode the above processes and resources to see how it works.
Here is my code :
#include <stdio.h>
#include <stdlib.h>
// Define maximum number of vertices in the graph
#define N 10
// Data structure to store graph
struct Graph {
// An array of pointers to Node to represent adjacency list
struct Node* head[N];
};
// A data structure to store adjacency list nodes of the graph
struct Node {
int dest;
struct Node* next;
};
// data structure to store graph edges
struct Edge {
int src, dest;
};
// Function to create an adjacency list from specified edges
struct Graph* createGraph(struct Edge edges[], int n)
{
unsigned i;
// allocate memory for graph data structure
struct Graph* graph = (struct Graph*)malloc(sizeof(struct Graph));
// initialize head pointer for all vertices
for (i = 0; i < N; i++)
graph->head[i] = NULL;
// add edges to the directed graph one by one
for (i = 0; i < n; i++)
{
// get source and destination vertex
int src = edges[i].src;
int dest = edges[i].dest;
// allocate new node of Adjacency List from src to dest
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
newNode->dest = dest;
// point new node to current head
newNode->next = graph->head[src];
// point head pointer to new node
graph->head[src] = newNode;
}
return graph;
}
// Function to print adjacency list representation of graph
void printGraph(struct Graph* graph){
int i;
for (i = 0; i < N; i++)
{
// print current vertex and all ts neighbors
struct Node* ptr = graph->head[i];
while (ptr != NULL)
{
printf("(%d -> %d)\t", i, ptr->dest);
ptr = ptr->next;
}
printf("\n");
}
}
// Directed Graph Implementation in C
int main(void)
{
// input array containing edges of the graph (as per above diagram)
// (x, y) pair in the array represents an edge from x to y
struct Edge edges[] =
{
{ 1, 2 }, { 2, 5 }, { 3, 1 }, { 4, 1 },
{ 1, 1 }, { 3, 1 }, { 5, 1 }, { 6, 2 },
{ 4, 4 }
};
// calculate number of edges
int n = sizeof(edges)/sizeof(edges[0]);
// construct graph from given edges
struct Graph *graph = createGraph(edges, n);
// print adjacency list representation of graph
printGraph(graph);
return 0;
}
-
I'm fairly new to code::blocks and how it works but I'm using it for an assignment at uni, basically, its implementing dijkstra's algorithm using ADTs and adjacency lists, the code works and I get an output but I get the error
Process returned -1073741819 (0xC0000005)
code for the minimum heap:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "graph.h"
#include "MinHeap.h"
#include "dynamicarraylist.h"
#include "singlelinkedlist.h"
#define CHAR_MAX 50
#define INFINITY 9999
///constructor function for the total heap, taking the capacity of the heap
///as an argument and returning the MinHeap struct
struct MinHeap* HeapConstructor(int V)
{
//create and allocate memory for a new heap struct
struct MinHeap* minHeap;
minHeap = malloc(sizeof(struct MinHeap));
//copy over the value of capacity and set numentities to 0
minHeap->numentities = 0;
//assign memory for the position pointer and for the node pointer
minHeap->Node = malloc(V * sizeof(struct MinHeapNode));
return minHeap;
}
struct MinHeapNode* HeapNodeConstructor(int distance,char* city)
{
struct MinHeapNode* minHeapNode;
minHeapNode = malloc(sizeof(struct MinHeapNode));
minHeapNode->distance = distance;
strcpy(minHeapNode->city,city);
return minHeapNode;
}
struct ShortestPath* ShortestPathConstructor()
{
//allocate enough memory for the struct
struct ShortestPath* shortestPath;
shortestPath = malloc(sizeof(struct ShortestPath));
//initialize with sensible values
shortestPath->distance = malloc(sizeof(int));
shortestPath->parent = NULL;
shortestPath->size = 0;
return shortestPath;
}
/// function to swap two nodes within a minimum heap, this allows us to sort
/// the heap, this is based on code found on stack overflow for swapping
/// two pointers found here: https://stackoverflow.com/questions/8403447/swapping-pointers-in-c-char-int
/// look at swap5 function of top answer
void NodeSwap(struct MinHeapNode** a, struct MinHeapNode** b)
{
//create a temporary node to copy the value of a across to
//using pointers so we dont have to return various structs
struct MinHeapNode* temp;
temp = *a;
*a = *b;
*b = temp;
}
///function to heapify a min Heap and update position of all nodes within heap
///this is required for updating distances from vertex when carrying out dijkstra's algorithm
/// code for parts of the heapify function is based on psuedo code from the wikipedia article about
/// binary heaps found at: https://en.wikipedia.org/wiki/Binary_heap
void minHeapify(struct MinHeap* minHeap, int index)
{
int smallest, left, right;
smallest = index;
left = (index * 2);
right = (index * 2) + 1;
//if we arent at the end of the heap and the left node is smaller than the node above it
if(left <= minHeap->numentities && minHeap->Node[left]->distance < minHeap->Node[smallest]->distance)
{
//smallest becomes the left child node of the heap
smallest = left;
}
// exact same procedure but they must be 2 separate if statements so that the function compares both both numbers
// in all cases
if(right <= minHeap->numentities && minHeap->Node[right]->distance < minHeap->Node[smallest]->distance)
{
smallest = right;
}
//if the smallest node is different from before starting the function then the heap is not yet heapified
if(smallest != index)
{
//swap nodes
NodeSwap(&minHeap->Node[smallest],&minHeap->Node[index]);
//recursive function so minHeapify is carried out within the function
minHeapify(minHeap,smallest);
}
}
/// simple function to check whether the heap is empty or not
/// so the function performing dijkstra's algorithm knows when to finish
/// takes the minHeap as parameters returning 0 if heap is empty and 1 if it isn't
int HeapIsEmpty(struct MinHeap* minHeap)
{
if(minHeap->numentities == 0)
{
return 0;
}
return 1;
}
///Builds our minimum heap using the graph and assigns the distances as infinite or
///0 for the source node then it heapifies until heap property is achieved
struct ShortestPath* BuildMinHeap(struct MinHeap* minHeap, struct List* graph, char* srccity,int V)
{
struct ShortestPath* shortestpath = ShortestPathConstructor();
int i;
//for total size of the minHeap
for(i = 0; i <= V; i++)
{
//if the source city and the city we're currently at are 0
//distance from source is 0
if(strcmp(srccity,graph->vertices[i].cityname) == 0)
{
minHeap->Node[minHeap->numentities + 1] = HeapNodeConstructor(0,srccity);
shortestpath[shortestpath->size + 1].distance = 0;
strcpy(shortestpath[shortestpath->size + 1].city,srccity);
}
//otherwise the distance is infinite
else
{
minHeap->Node[minHeap->numentities + 1] = HeapNodeConstructor(INFINITY,graph->vertices[i].cityname);
shortestpath[shortestpath->size + 1].distance = INFINITY;
strcpy(shortestpath[shortestpath->size + 1].city,graph->vertices[i].cityname);
}
shortestpath->size++;
minHeap->numentities++;
}
//moves through the heap making sure heap property is satisfied
for(i = minHeap->numentities / 2; i > 0; i--)
{
minHeapify(minHeap,i);
}
return shortestpath;
}
///takes out and returns the minimum node from a heap given as an input
struct MinHeapNode* removeMin(struct MinHeap* minHeap)
{
if(minHeap->numentities != 0)
{
//remove the root node of the minimum heap and store it
struct MinHeapNode* root = minHeap->Node[1];
//move the last element of the heap to the top
minHeap->Node[1] = minHeap->Node[(minHeap->numentities) - 1];
minHeap->numentities--;
minHeapify(minHeap,1);
return root;
}
else
{
printf("\nheap is empty \n");
}
}
///search through the heap for given city name returning the index
///utilises a linear search algorithm
int HeapSearch(struct MinHeap* minHeap,char* cityname)
{
int i;
for(i = 1; i <= minHeap->numentities; i++)
{
if(strcmp(minHeap->Node[i]->city,cityname) == 0)
{
return i;
}
}
return -1;
}
/// decreases key(value) stored within the node from what we defined infinity as being to the shortest currently available path from our source node
/// to the current node
void DecreaseKey(struct MinHeap* minHeap,int x,int newdistance)
{
//find a return the index of our required city to decrease the key of
int i = x;
//compares new distance with currently stored distance and if bigger than the other function stops
if(newdistance > minHeap->Node[i]->distance)
{
return;
}
else
{
//move to index node and update value of distance with distance
minHeap->Node[i]->distance = newdistance;
}
//travel up tree until it is heapified by comparing the index node with its parent node
while(minHeap->Node[i]->distance < minHeap->Node[i/2]->distance && i > 1)
{
//swap node with parent node
NodeSwap(&minHeap->Node[i],&minHeap->Node[i/2]);
//move to parent node
i = i/2;
}
}
void levelorderTraversal(struct MinHeap* minHeap)
{
int i ;
for(i = 1; i < minHeap->numentities; i++)
{
printf("\n %s %d ",minHeap->Node[i]->city, minHeap->Node[i]->distance);
}
}
void shortestPathDisplay(struct ShortestPath* shortestPath)
{
int i;
printf("City Distance From Source");
for(i = 1; i < shortestPath->size;i++)
{
printf("\n%s \t\t %d",shortestPath[i].city,shortestPath[i].distance);
}
}
///search the array list and return index of that search or a -1 if failure
///very important function used in AddEdge function, takes a List struct and a cityname
///as arguments
int ShortestPathSearch(struct ShortestPath* shortestPath, char* cityname)
{
int i;
//seaches from beginning to end of arraylist
for(i = 1 ; i <= shortestPath->size; i++)
{
//strcmp() function compares two input strings, if they are the same it returns a 0
if(strcmp(shortestPath[i].city,cityname) == 0)
{
// we want the index this vertex was found at
return i;
}
}
//if failure return -1
return -1;
}
void dijkstra(struct List* graph,char* startcity)
{
//two intermediate integer variables to find distance at various vertices to get minimum weight overall
int V = graph->numcities;
int added_distance;
struct MinHeap* minHeap = HeapConstructor(V);
struct ShortestPath* shortestPath = ShortestPathConstructor();
//builds our minimum heap and heapifies it
shortestPath = BuildMinHeap(minHeap,graph,startcity,V);
///shortestPathDisplay(shortestPath,V);
///levelorderTraversal(minHeap);
while(minHeap->Node != NULL)
{
levelorderTraversal(minHeap);
//extract shortest distance in heap
struct MinHeapNode* shortestNode = removeMin(minHeap);
printf("removed node is %s distance %d \n",shortestNode->city,shortestNode->distance);
//searches for removed city within index and adds the current distance associated with this
//city
int z = ShortestPathSearch(shortestPath,shortestNode->city);
added_distance = shortestPath[z].distance;
printf("current dist from source: %d \n",added_distance);
//searches for the index of the removed city within our adjacency list and stores it
int u = ArrayListSearch(graph,shortestNode->city);
//assigns a new struct of linkedNode type for traversing through adjacenct nodes
struct linkedNode* adjListTraverse = graph->vertices[u].linkedList->head;
//while not at end of list
while(adjListTraverse != NULL)
{
printf("city: %s distance: %d \n",adjListTraverse->cityname,adjListTraverse->weight);
//looks for the new adjacenct city within the heap and our output array
int v = ShortestPathSearch(shortestPath,adjListTraverse->cityname);
printf("v = %d \n",v);
int x = HeapSearch(minHeap,adjListTraverse->cityname);
printf("x = %d \n",x);
//if it is in the array and the minHeap and the final distance is not finalised
//if x = -1 city is not in heap anymore and can be skipped entirely
if(adjListTraverse->weight + added_distance < shortestPath[v].distance)
{
shortestPath[v].distance = adjListTraverse->weight + added_distance;
//update with new distances
DecreaseKey(minHeap,x,shortestPath[v].distance);
}
adjListTraverse = adjListTraverse->next;
}
shortestPathDisplay(shortestPath);
printf("\n");
}
}
Sorry the code is horrendously long I've been trying to find the cause of the problem, I think it might be to do with a pointer not having memory allocated to it but I cant find any pointer like that
I use this data structure to store a graph:
struct Vertex
{
struct Line *a;
struct Line *b;
int X;
int Y;
struct Vertex *next;
struct Edge *edges;
int edgeCount;
};
struct Edge
{
struct Vertex *dst;
struct Vertex *src;
struct Edge *next;
float weight;
bool included;
bool visited;
};
I generate a linked list of vertices(the list is my graph) in a loop:
struct Edge *edge= malloc(sizeof(struct Edge));
////here I add edge's data
if(graph->edges == NULL)
{
graph->edges = edge;
}
else
{
edge->next = graph->edges;
}
And now I need to permute resulting array. It is simple with common array of integers:
void swap(int a, int b)
{
int temp = a;
a = b;
b = temp;
}
void permutation(int* randomArray, int numIndex)
{
for (i = 0; i < numIndex; i++)
{
int randomOffset = rand() % (numIndex - i);
swap(randomArray[i], randomArray[i+randomOffset]);
}
}
But how to do the same with linked list?
Create an array of struct Edge * that contains all edges, built when the linked list is created, permute that array, rebuild the linked list.
The variables
struct Edge *pedges[MAXEDGES]; // or allocate dynamically (see below)
int nedges = 0;
then when list is created
struct Edge *edge= malloc(sizeof(struct Edge)); // your code
pedges[nedges++] = edge;
permutations are done the same way
void permuteEdges(struct Edge *pe, int ne) {
int i;
for (i = 0 ; i < ne ; i++) {
int randomOffset = rand() % (ne - i);
swap(pe[i], pe[i+randomOffset]);
}
}
finally, rebuild the linked list
for (i = 0 ; i < ne ; i++) {
if ( ! i) {
graph->edges = pe[i];
}
else {
pe[i-1]->next = pe[i];
}
}
ensure the last item next property points to NULL
pe[ne-1]->next = NULL;
Note that you could allocate pedges dynamically (to be freed after use). For instance if you use the array for a single shuffle, there is no need to keep that amount of memory in the heap.
Dynamic allocation
struct Edge *pedges = malloc(MAXEDGES * sizeof(*pedges));
...use it...
free(pedges);
I'm trying to implement a graph to store a list of data from a text file such as the following:
0,1 (node 0 links to 1)
0,2 (node 0 links to 2)
1,2 (node 1 links to 2)
2,1 (node 2 links to 1)
Anyways I come across trouble when it comes down to defining the structures. I'm torn between using a matrix or adjacent lists, but I think I will go with lists, I am just not sure how to define the structures. Should I use variable sized arrays, linked lists or something else? Which way would be the easiest?
struct grph{
};
struct node{
//ID of the node
int id;
};
Second, how do I store the data into this graph, this is where I come across the most trouble. Essentially, I thought it would be easy like linked lists where you just keep adding a node to the end. The difference here is that each node can point to many different nodes or to none at all. How do I link the graph structure with all the linked node structures?
When using linked lists for example, how would I store what node 0 connects to in the example above? I understand you use a matrix or list/array, but I'm seriously getting confused because of the lack of examples of such implementations in C. Any examples I found just made it much worse then I was before.
This is just an example:
struct node{
int id;
struct node **out;
int num_out;
/* optional: if you want doubly links */
struct node **in;
int num_in;
};
/* quick access to a node given an id */
struct node *node_list;
/* connect 'from' to 'to' */
void link(struct node *graph, int from, int to) {
struct node *nfrom = &node_list[from],
*nto = &node_list[to];
nfrom->num_out++;
nfrom->out = realloc(nfrom->out,
sizeof(struct node*) * nfrom->num_out);
nfrom->out[num_out-1] = nto;
/* also do similar to nto->in if you want doubly links */
}
In answer to your first question: adjacency matrix vs adjacency lists? If you expect your graph to be dense, i.e. most nodes are adjacent with most other nodes, then go for the matrix as most operations are much easier on matrices. If you really need a transitive closure, then matrices are probably better also, as these tend to be dense. Otherwise adjacency lists are faster and smaller.
A graph would look as follows:
typedef struct node * node_p;
typedef struct edge * edge_p;
typedef struct edge
{ node_p source, target;
/* Add any data in the edges */
} edge;
typedef struct node
{ edge_p * pred, * succ;
node_p next;
/* Add any data in the nodes */
} node;
typedef struct graph
{ node_p N;
} graph;
The N field of graph would start a linked list of the nodes of the graph using the next field of node to link the list. The pred and succ can be arrays allocated using malloc and realloc for the successor and predecessor edges in the graph (arrays of pointers to edges and NULL terminated). Even though keeping both successor and predecessors may seem redundant, you will find that most graph algorithms like to be able to walk both ways. The source and target field of an edge point back to the nodes. If you don't expect to store data in the edges, then you could let the pred and succ arrays point back directly to the nodes and forget about the edge type.
Don't try to use realloc on N in the graph because all the addresses of the nodes may change and these are heavily used in the remainder of the graph.
P.S: Personally I prefer circular linked lists over NULL ended linked lists, because the code for most, if not all, operations are much simpler. In that case graph would contain a (dummy) node instead of a pointer.
You could do something like this:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct
{
void* pElements;
size_t ElementSize;
size_t Count; // how many elements exist
size_t TotalCount; // for how many elements space allocated
} tArray;
void ArrayInit(tArray* pArray, size_t ElementSize)
{
pArray->pElements = NULL;
pArray->ElementSize = ElementSize;
pArray->TotalCount = pArray->Count = 0;
}
void ArrayDestroy(tArray* pArray)
{
free(pArray->pElements);
ArrayInit(pArray, 0);
}
int ArrayGrowByOne(tArray* pArray)
{
if (pArray->Count == pArray->TotalCount) // used up all allocated space
{
size_t newTotalCount, newTotalSize;
void* p;
if (pArray->TotalCount == 0)
{
newTotalCount = 1;
}
else
{
newTotalCount = 2 * pArray->TotalCount; // double the allocated count
if (newTotalCount / 2 != pArray->TotalCount) // count overflow
return 0;
}
newTotalSize = newTotalCount * pArray->ElementSize;
if (newTotalSize / pArray->ElementSize != newTotalCount) // size overflow
return 0;
p = realloc(pArray->pElements, newTotalSize);
if (p == NULL) // out of memory
return 0;
pArray->pElements = p;
pArray->TotalCount = newTotalCount;
}
pArray->Count++;
return 1;
}
int ArrayInsertElement(tArray* pArray, size_t pos, void* pElement)
{
if (pos > pArray->Count) // bad position
return 0;
if (!ArrayGrowByOne(pArray)) // couldn't grow
return 0;
if (pos < pArray->Count - 1)
memmove((char*)pArray->pElements + (pos + 1) * pArray->ElementSize,
(char*)pArray->pElements + pos * pArray->ElementSize,
(pArray->Count - 1 - pos) * pArray->ElementSize);
memcpy((char*)pArray->pElements + pos * pArray->ElementSize,
pElement,
pArray->ElementSize);
return 1;
}
typedef struct
{
int Id;
int Data;
tArray LinksTo; // links from this node to other nodes (array of Id's)
tArray LinksFrom; // back links from other nodes to this node (array of Id's)
} tNode;
typedef struct
{
tArray Nodes;
} tGraph;
void GraphInit(tGraph* pGraph)
{
ArrayInit(&pGraph->Nodes, sizeof(tNode));
}
void GraphPrintNodes(tGraph* pGraph)
{
size_t i, j;
if (pGraph->Nodes.Count == 0)
{
printf("Empty graph.\n");
}
for (i = 0; i < pGraph->Nodes.Count; i++)
{
tNode* pNode = (tNode*)pGraph->Nodes.pElements + i;
printf("Node %d:\n Data: %d\n", pNode->Id, pNode->Data);
if (pNode->LinksTo.Count)
{
printf(" Links to:\n");
for (j = 0; j < pNode->LinksTo.Count; j++)
{
int* p = (int*)pNode->LinksTo.pElements + j;
printf(" Node %d\n", *p);
}
}
}
}
void GraphDestroy(tGraph* pGraph)
{
size_t i;
for (i = 0; i < pGraph->Nodes.Count; i++)
{
tNode* pNode = (tNode*)pGraph->Nodes.pElements + i;
ArrayDestroy(&pNode->LinksTo);
ArrayDestroy(&pNode->LinksFrom);
}
ArrayDestroy(&pGraph->Nodes);
}
int NodeIdComparator(const void* p1, const void* p2)
{
const tNode* pa = p1;
const tNode* pb = p2;
if (pa->Id < pb->Id)
return -1;
if (pa->Id > pb->Id)
return 1;
return 0;
}
int IntComparator(const void* p1, const void* p2)
{
const int* pa = p1;
const int* pb = p2;
if (*pa < *pb)
return -1;
if (*pa > *pb)
return 1;
return 0;
}
size_t GraphFindNodeIndexById(tGraph* pGraph, int Id)
{
tNode* pNode = bsearch(&Id,
pGraph->Nodes.pElements,
pGraph->Nodes.Count,
pGraph->Nodes.ElementSize,
&NodeIdComparator);
if (pNode == NULL)
return (size_t)-1;
return pNode - (tNode*)pGraph->Nodes.pElements;
}
int GraphInsertNode(tGraph* pGraph, int Id, int Data)
{
size_t idx = GraphFindNodeIndexById(pGraph, Id);
tNode node;
if (idx != (size_t)-1) // node with this Id already exist
return 0;
node.Id = Id;
node.Data = Data;
ArrayInit(&node.LinksTo, sizeof(int));
ArrayInit(&node.LinksFrom, sizeof(int));
if (!ArrayInsertElement(&pGraph->Nodes, pGraph->Nodes.Count, &node))
return 0;
qsort(pGraph->Nodes.pElements,
pGraph->Nodes.Count,
pGraph->Nodes.ElementSize,
&NodeIdComparator); // maintain order for binary search
return 1;
}
int GraphLinkNodes(tGraph* pGraph, int IdFrom, int IdTo)
{
size_t idxFrom = GraphFindNodeIndexById(pGraph, IdFrom);
size_t idxTo = GraphFindNodeIndexById(pGraph, IdTo);
tNode *pFrom, *pTo;
if (idxFrom == (size_t)-1 || idxTo == (size_t)-1) // one or both nodes don't exist
return 0;
pFrom = (tNode*)pGraph->Nodes.pElements + idxFrom;
pTo = (tNode*)pGraph->Nodes.pElements + idxTo;
// link IdFrom -> IdTo
if (bsearch(&IdTo,
pFrom->LinksTo.pElements,
pFrom->LinksTo.Count,
pFrom->LinksTo.ElementSize,
&IntComparator) == NULL) // IdFrom doesn't link to IdTo yet
{
if (!ArrayInsertElement(&pFrom->LinksTo, pFrom->LinksTo.Count, &IdTo))
return 0;
qsort(pFrom->LinksTo.pElements,
pFrom->LinksTo.Count,
pFrom->LinksTo.ElementSize,
&IntComparator); // maintain order for binary search
}
// back link IdFrom <- IdTo
if (bsearch(&IdFrom,
pTo->LinksFrom.pElements,
pTo->LinksFrom.Count,
pTo->LinksFrom.ElementSize,
&IntComparator) == NULL) // IdFrom doesn't link to IdTo yet
{
if (!ArrayInsertElement(&pTo->LinksFrom, pTo->LinksFrom.Count, &IdFrom))
return 0;
qsort(pTo->LinksFrom.pElements,
pTo->LinksFrom.Count,
pTo->LinksFrom.ElementSize,
&IntComparator); // maintain order for binary search
}
return 1;
}
int main(void)
{
tGraph g;
printf("\nCreating empty graph...\n");
GraphInit(&g);
GraphPrintNodes(&g);
printf("\nInserting nodes...\n");
GraphInsertNode(&g, 0, 0);
GraphInsertNode(&g, 1, 101);
GraphInsertNode(&g, 2, 202);
GraphPrintNodes(&g);
printf("\nLinking nodes...\n");
GraphLinkNodes(&g, 0, 1);
GraphLinkNodes(&g, 0, 2);
GraphLinkNodes(&g, 1, 2);
GraphLinkNodes(&g, 2, 1);
GraphPrintNodes(&g);
printf("\nDestroying graph...\n");
GraphDestroy(&g);
GraphPrintNodes(&g);
// repeat
printf("\nLet's repeat...\n");
printf("\nCreating empty graph...\n");
GraphInit(&g);
GraphPrintNodes(&g);
printf("\nInserting nodes...\n");
GraphInsertNode(&g, 1, 111);
GraphInsertNode(&g, 2, 222);
GraphInsertNode(&g, 3, 333);
GraphPrintNodes(&g);
printf("\nLinking nodes...\n");
GraphLinkNodes(&g, 1, 2);
GraphLinkNodes(&g, 2, 3);
GraphLinkNodes(&g, 3, 1);
GraphPrintNodes(&g);
printf("\nDestroying graph...\n");
GraphDestroy(&g);
GraphPrintNodes(&g);
return 0;
}
Output (ideone):
Creating empty graph...
Empty graph.
Inserting nodes...
Node 0:
Data: 0
Node 1:
Data: 101
Node 2:
Data: 202
Linking nodes...
Node 0:
Data: 0
Links to:
Node 1
Node 2
Node 1:
Data: 101
Links to:
Node 2
Node 2:
Data: 202
Links to:
Node 1
Destroying graph...
Empty graph.
Let's repeat...
Creating empty graph...
Empty graph.
Inserting nodes...
Node 1:
Data: 111
Node 2:
Data: 222
Node 3:
Data: 333
Linking nodes...
Node 1:
Data: 111
Links to:
Node 2
Node 2:
Data: 222
Links to:
Node 3
Node 3:
Data: 333
Links to:
Node 1
Destroying graph...
Empty graph.
It seems quite like my working, social networking...
You could define the node and links seperately. In c language, you could define as:
struct graph_node{
int id;
struct node_following *following;
struct graph_node *next_node;
}
struct node_following{
int id;
struct node_following *next_node;
}
For your example, the result is:
root -> node0 -> node1 -> node2
The content of root might be: id = -1; following=NULL; next_node= node0
The content of node0 might be: id = 0; next_node = node1; following point to a list of node_following as:
following -> {1, address of next node} -> {2, NULL}
The content of node1 might be: id = 1; next_node = node2; following point to a list of node_following as:
following -> {2, NULL}
The content of node2 might be: id = 2; next_node = NULL; following point to a list of node_following as:
following -> {1, NULL}
Essentially, it is a quesition on how to store a two-dimensional matrix. If the matrix is sparse, use the linked list. Otherwise, bitmap is a better solution.