Dijkstra's algorithm (updating the heap) - c

I am implementing Dijkstra's algorithm using a heap data structure. I also use an array that keeps track of the "probable minimum distances" of the nodes. The problem is when I am updating the array, how to update the corresponding values in the heap?
ok here's the code
typedef struct temp
{
int nodeTag;
int weight;
struct temp *next;
}myStruct; //this structure corresponds to the elements of the linked list
typedef struct temp *link;
typedef struct
{
int nodeTag; //each node has an integer nodeTag associated with it
link l;
}head; //the head of the elements of the adjacency list
typedef struct {
head *adjList;
int numNodes;
int numEdges;
} Graph;
typedef struct {
int possibleMinWeight;
int minFound; //minFound==1 if true min is found
} dummy;
dummy *dijkstraSSSP(Graph G, int nodeTag)
{
minHeap H=createEmptyHeap(G.numNodes);
while(i=0;i<G.numNodes;i++)
{
if(i!=nodeTag)
H.A[i].priority=INFINITY;
else
H.A[i].priority=0;
H.A[i].nodeTag=i;
}
convertIntoHeap(H);
int min;
dummy *A=(dummy *)malloc(sizeof(int)*G.numNodes);
A[nodeTag-1].possibleMinWeight=0;
A[nodeTag-1].minFound=1;
while(!isEmpty(H))
{
element e=findMin(H); H=deleteMin(H);
A[e.nodeTag-1].minFound=1;
link l=G.adjList[e.nodeTag-1].l;
while(l!=NULL)
{
if(A[l->nodeTag-1].minFound==0); //its true minimum distance is yet to be found
{
if(A[l->nodeTag-1].possibleMinWeight>A[x-1].possibleMinWeight+(l->weight))
A[l->nodeTag-1].possibleMinWeight=A[x-1]+(l->weight);
}
l=l->next;
}
}
return A;
}

To write DecreaseKey, you need the priority-queue implementation to maintain a map from nodeTags to locations in the queue. That means updating this map whenever the binary-heap data structure calls for a swap or perhaps choosing a pointer-based implementation like pairing heaps that never moves nodes in memory.
Unless you have a large, somewhat dense graph, DecreaseKey isn't worth it; just insert a node multiple times and ignore duplicate results from ExtractMin. (To detect duplicates: every time I've implemented Dijkstra, I've needed either the distances or the tree. In my programming languages of choice, it's easy enough to shake loose a bit from either array to remember whether each node has been visited.)

Related

sort a linked list of struct in c

I am trying to sort a linked list in an ascending order according to the element of the struct"capacite" . But it doesn't give a result. What is the mistake i am making? Here is my code
typedef struct avion avion;
typedef avion* aliste;
struct avion
{
char code[20];
int capacite;
char etat;
int date;
int nvols;
aliste svt;
};
i have created the list.
and following the function that sort it:
void tri(aliste L)
{
aliste i,j,min,tmp;
for (i=L; i->svt != NULL; i=i->svt)
{
min=i;
for (j=i->svt; j != NULL; j=j->svt)
{
if (j->capacite < min->capacite)
min=j;
}
if (min != i)
{
tmp=min;
min=i;
i=tmp;
}
}
}
It looks like you are trying to bubble sort your list. A quick and dirty fix would be to swap the contents of your nodes:
void tri(aliste L)
{
aliste i,j,min;
avion tmp;
...
if (min != i)
{
tmp=*min;
*min=*i;
*i=tmp;
}
}
}
The good news here is that the L pointer passed from the caller still points to the beginning of the list. The downside if that it copies the structures while changing only the svt pointers would be much more efficient. But:
you will have to return to the caller a pointer to the new head
moving elements from a singly linked list requires to record the previous element
As you use bubble sort which is not a very efficient algorithme, I assume that you only intend to process small lists and that performance is not essential, so you are on your own...
A common way to implement a linked list of structs in C is in https://www.geeksforgeeks.org/linked-list-set-1-introduction/
Basically inside the struct there is a pointer next to the next node in the linked list, what establishes the linked list functionality :
struct Node {
int data;
struct Node* next;
};
For this more common implementation of a linked list in C you find source code for many sorting algorithms (qsort, mergesort,...) on the net. You have to implement functionality for more than one parameter in such an example because your nodes (of the linked list) have multiple data fields...
Sorting linked list by multiple parameters
typedef avion* aliste; Is it a good idea to typedef pointers?

Comparing all elements with each other inside a nested linked list in C

I have a nested linked list of the form:
struct child
{
char name[15];
int num;
struct child *next;
};
struct parent
{
char name[15];
struct child *head_child;
struct parent *next;
};
struct parent *head_parent;
and basic comparison function:
_Bool compare(int num_1, int num_2)
{
if(num_1 == num_2)
return 1; // Bad; conflicting numbers
else
return 0; // Good!
}
For example, a user entered data such that the columns (A, B, C, D, E) represent elements in the parent list, and rows (1-5), represent elements in the child list as illustrated below (pardon my MS Paint skills).
Q: If every working combination of A+B+C+D+E had to be found, where no two numbers can be the same, what algorithms could be used?
I am planning on storing the resulting successful list in another struct with pointers later for display like such:
struct working
{
char *parent_name;
char *child_name;
struct working *next;
};
struct combination
{
struct working *head;
struct combination *next;
};
If possible, provide a basic example with for/while loops, and if you can show the complexity, that would be a huge bonus :)

Qsort with Huffman tree

I have a problem where I have to build a Huffman tree, I understand the concept behind the problem and I know how to do it. However, I have discovered the reason for my code going wrong is to do with my sorting functions. I want to sort the list every time I input a new node into the list. I have a structure and in it I have frequency, I have made an array of structures that character are store in from a file.
My problem lies with creating the nodes, a new node is created and points to two characters in the array. However, when I then sort this list the pointers change to other characters. This happens for every step and causes it to be completely wrong.
My qsort call in main is like this:
qsort(list, n, sizeof(Node), intcompare);
and my intcompare function is like this:
int intcompare(const void *a, const void *b)
{
int freq1 = ((Node*)a)->frequency;
int freq2 = ((Node*)b)->frequency;
if (freq1 == freq2){
return 0;
}
else if (freq1 < freq2){
return 1;
}
else{
return -1;
}
}
my structure is like this:
typedef struct node{
char character;
int frequency;
struct node *left;
struct node *right;
}Node;
My list gets sorted correctly by frequency each time I call qsort.
Why would this change where the pointers in my struct are pointing to?
Thanks in advance!!
qsort moves the structures around in the array. So if there exists a left pointer that points to character X at index 3 in the array, and qsort moves X to index 16, then the left pointer won't be pointing at X anymore. It will be pointing to whatever qsort put at index 3. Long story short, you need to recompute all of the left and right pointers after every sort.

DFS: Existence of Spanning Tree

Can a depth-first-search be used to determine if some graph is connected given access to an arrays of edges and vertices of unknown size, with only the starting vertex as the input data?
struct node {
int parent, rank;
};
typedef struct node node;
struct edge {
int fromvertex, tovertex;
float weight;
};
typedef struct edge edge;
node* nodes;
edge* edges;
int hasspantree(int startvertex)
{
//find spanning tree?
}
Nodes and edges are assigned in a function that runs before the depth-first search, as so:
scanf("%d", nodecount);
scanf("%d", edgecount);
if ((nodes = malloc(*nodecount * sizeof(node))) == NULL) {
printf("nodes malloc failed"); exit(1);
}
if((edges = malloc(*edgecount * sizeof(edge))) == NULL) {
printf("edges malloc failed"); exit(1);
}
I can do it given this function declaration:
int hasspantree(int startvertex, int edgecount, int nodecount)
But I'd like to be able to do it with the previous declaration.
The short answer is, given your data (the starting node and 2 lists of unknown size), that is impossible to perform the DFS, simply because you don't know your graph (you don't know what is in memory graph-related data or garbage, as you don't know how to stop). So you cannot analyse an unknown graph. The question is whether the size of the graph (by the size of the graph I mean the size of the 2 arrays that define the graph in your case) is explicit (and it isn't, as your function doesn't take a size parameter) or implicit (the data structure contains the size or has a particular way of indicating it). So, you can use a terminator (a NULL pointer, similar to the use of the NUL character in strings) to indicate the end of the array. Also, you could have a global variable, but we all know that's not a good practice.

how do we represent an edge list given that we have a graph with nodes and edges.am not talking about adjacency lists

what is an edge list?not an adjacency list..
and how do we represent an edge list in C programming provided that we are given a graph with nodes and edges?
Here is the base structure
struct Edge
{
int id;
int weight; // If you need one
vector<Edge *> neighbours; // List of references on your neightbours
}
vector<Edge> graph;
But as Michael noticed it does look like a homework :) Take a look at boot graphs library.
UPDATE C version
struct Edge
{
int id;
int weight; // If you need one
Edge *next; // Next edge in the list
Edge *neighbours; // List of neightbours
}
Edge *graph;
Using the definition of edge list found here, and assuming undirected edges, emulating the "human" representation would be a good first attempt:
typedef struct UndirectedEdge {
int ends[2];
};
Where your vertices are all numbered within the range of int. If they're directed:
typedef struct DirectedEdge {
int from;
int to;
}
Add other properties as required, with type appropriate to your problem:
typedef struct WeightedEdge {
size_t from;
size_t to;
double weight;
}
Note that a list of vertices isn't required, unless to map integer vertex indices to human-readable labels if they exist in your initial problem. Furthermore, you should define a suitable comparison function for your edge list to ensure uniqueness of your edges depending on properties of your graph, such as directedness.
typedef struct EdgeList {
size_t edge_count;
EdgeType *edges;
}
_Bool undirected_edge_equal(UndirectedEdge *this, UndirectedEdge *other) {
return this->ends[0] == other->ends[0] && this->ends[1] == other->ends[1]
|| this->ends[0] == other->ends[1] && this->ends[1] == other->ends[0]
}
_Bool directed_edge_equal(DirectedEdge *this, DirectedEdge *other) {
return this->from == other->from && this->to == other->to;
}

Resources