Adjacency List in C for undirected (unweighted) graph - c

Here is my code:
#define V 5
typedef struct edge* link;
//structure for reprenting edges
typedef struct edge{
int dst; //number of destination node
//int weight; //for weigthed graphs
link next; //link to next edge
} edge_t;
link new_edge(int dst, link next) {
link edge = (link) malloc(sizeof(edge_t));
edge->dst = dst;
edge->next = next;
return edge;
}
int main() {
link edge;
link adj[V];
//the array contains V pointers to lists of edges
//each list for each node of my graph
int i;
int j;
//all lists are empty at beginning
for (i = 0; i < V; i ++) {
adj[i] = NULL;
}
printf("input the edges:\n");
while (scanf("%d %d", &i, &j) == 2) {
adj[i] = new_edge(j, adj[i]);
//in the list for node i
//put the edge to node j
adj[j] = new_edge(i, adj[j]); //if it is undirect
//in the list for node j
//put the edge to node i
}
printf("adjacency list is: \n");
//cycle over the nodes
for (i=0; i<V; i++) {
if (adj[i] == NULL) {
printf("%d is null list\n", i);
}
//print all the edges for that node
for (edge = adj[i]; edge != NULL; edge = edge -> next) {
printf("edge %d -> %d\n", i, edge->dst);
}
}
}
INPUT:
0 1
0 2
1 3
stop
OUTPUT:
adjacency list is:
edge 0 -> 2
edge 0 -> 1
edge 1 -> 3
edge 1 -> 0
edge 2 -> 0
edge 3 -> 1
4 is null list
This image shows how my new_edge function works, blue area(in pic) is changing so I can traverse through the list, so my question is why blue area is equal to NULL?, cause it is pointing to last item in the list, I thought it won't be NULL(P.S I verified it is null when I traversed through the list in order to print it).

The elements of adj are pointers to nodes, not nodes.
On the other hand, what next in the nodes point at are nodes, not pointers to nodes.
Therefore, next will not point at the elements of adj.
This is how your code actually work:
As you see, the pointers are not looping back and your blue area (elements of adj that have nodes added) is not equal to NULL.

Related

Binary search tree traversal in C

I have this function that traverses a binary search tree and appends nodes to a list if they are between a given lower and upper bound.
// n - the current node
// l - a list to accumulate results
static void doTreeSearchBetween(Tree t, Node n, Record lower,
Record upper, List l) {
// empty tree
if (n == NULL) {
return;
}
int cmpUpper = t->compare(n->rec, upper);
int cmpLower = t->compare(n->rec, lower);
// search left subtree
doTreeSearchBetween(t, n->left, lower, upper, l);
// if node if between lower and upper records append to list
if (cmpLower >= 0 && cmpUpper <= 0) {
ListAppend(l, n->rec);
}
// search right subtree
doTreeSearchBetween(t, n->right, lower, upper, l);
}
I realised the issue with this code is that it traverses the entirety of the list in-order, making it very inefficient and I'm looking for a way that would allow me to visit as few nodes as possible. The logic isn't working out for me, I was wondering if anyone had any ideas? I tried adding a couple if statements for whenever the current node is less than the lower and greater than the upper bound, that didn't work out for me.
An example of the output:
Inserting: 11 13 17 19 23 29 31 37 41 43
Searching between 10 and 20
Search returned: 11 13 17 19
Type defs:
typedef struct node *Node;
struct node {
Record rec;
Node left;
Node right;
};
struct tree {
Node root;
int (*compare)(Record, Record);
};
struct list {
Record *items;
int numItems;
int maxItems;
};
struct record {
char familyName[MAX_FAMILY_NAME_LENGTH + 1];
char givenName[MAX_GIVEN_NAME_LENGTH + 1];
};
You should rely on the comparisons to determine whether to recurse on the left and/or right branches:
if the tree node is below the lower bound, its left subtree can be pruned.
if the tree node is above the upper bound, its right subtree can be pruned.
Assuming it is empty at the root node, the list will be sorted by construction.
// n - the current node
// l - a list to accumulate results
static void doTreeSearchBetween(Tree t, Node n, Record lower,
Record upper, List l) {
// empty tree
if (n == NULL) {
return;
}
int cmpUpper = t->compare(n->rec, upper);
int cmpLower = t->compare(n->rec, lower);
if (cmpLower >= 0) {
// search left subtree
doTreeSearchBetween(t, n->left, lower, upper, l);
// if node if between lower and upper records append to list
if (cmpUpper <= 0) {
ListAppend(l, n->rec);
}
}
if (cmpUpper <= 0) {
// search right subtree
doTreeSearchBetween(t, n->right, lower, upper, l);
}
}

BFS traversal, same node being accessed twice

I am trying to figure out how to write BFS algorithm in C
and I got this
typedef struct graph {
int numnodes;
int **edges;
} graph;
void bfs(graph *g, int start) {
int visited[g->numnodes], queue[g->numnodes], front =- 1, rear =- 1;
for (int i = 0; i < g->numnodes; i++) {
visited[i] = 0;
}
front++;
queue[++rear] = start;
visited[start] = 1;
while (front <= rear) {
start = queue[front++];
printf("%d\t", start);
for (int i = 0; i < g->numnodes; i++) {
if (g->edges[start][i] == 1 && !visited[i]) {
queue[++rear] = i;
}
}
}
}
for graph looking like graph.
When I print out BFS, it seems to give me
0 1 2 2 3 4
I'm not entirely sure what's wrong here, some help would be appreciated.
I am not sure if BFS is the right term for what you are doing. Your graph is not a tree and with a node having multiple parent nodes it is hard to tell on what level a node really is.
But to make your code work as expected, you just need to fix your missing use of visited array:
if (g->edges[start][i] == 1 && !visited[i]) {
queue[++rear] = i;
visited[i] = 1;
}
Create an actual graph and go through that (e.g. struct for each node, nodes linked via pointers). Right now what you have is an array that you go through item by item if I understand correctly.
You can use an array to store one level of the graph.
0 (first level)
2 1 (second level)
...

Check if undirected graph is connected

I have been making an algorithm that builds a Minimum Spanning Tree where I insert the number of cities (vertexes), airports (edges connecting to a "sky" vertex - vertex 0) and the number of roads (edges connected to other cities).
I then insert the city the airport (source vertex) is built and the cost (edge cost).
After this, I insert the cities connected by roads (source and destiny vertexes) and the cost (edge cost).
The outputs are the MST cost, the number of airports and number of roads.
I already have these mechanisms working but they are a bit buggy. I can't seem to fix these issues.
Also, I was wondering if I can make a function that detects if the undirected graph in the MST is connected (all vertexes are connected). If the function detects that the MST is not connected, the program should output "Insuficient information.".
Full code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// A structure to represent a weighted edge in graph.
struct Edge {
int src, dest, weight;
};
// A structure to represent a connected, undirected and weighted graph.
struct Graph {
// V -> Vertex Number (Number of cities), E -> Number of edges (Number of roads + airport connections).
int V;
int E;
// The graph is represented as an array of edges.
// Since the graph is undirected, the edge
// from src to dest is also edge from dest
// to src. Both are counted as 1 edge here.
struct Edge* edge;
};
// Creates a graph with V vertexes and E edges.
struct Graph* createGraph(int V, int E)
{
struct Graph* graph = malloc(sizeof *graph);
graph->V = V;
graph->E = E;
graph->edge = (struct Edge*)malloc(E * sizeof(struct Edge));
return graph;
};
// A structure to represent a subset for union-find.
struct subset {
int parent;
int rank;
};
// A utility function to find set of an element (uses path compression technique).
int find(struct subset subsets[], int i)
{
// Find root and make root as parent of i (uses path compression technique).
if (subsets[i].parent != i)
subsets[i].parent
= find(subsets, subsets[i].parent);
return subsets[i].parent;
}
// A function that does union of two sets of x and y (uses union by rank).
void Union(struct subset subsets[], int x, int y)
{
int xroot = find(subsets, x);
int yroot = find(subsets, y);
// Attach smaller rank tree under root of high rank tree (Union by Rank).
if (subsets[xroot].rank < subsets[yroot].rank)
subsets[xroot].parent = yroot;
else if (subsets[xroot].rank > subsets[yroot].rank)
subsets[yroot].parent = xroot;
// If ranks are same, then make one as root and increment its rank by one.
else
{
subsets[yroot].parent = xroot;
subsets[xroot].rank++;
}
}
// Compare two edges according to their weights.
// Used in qsort() for sorting an array of edges.
int myComp(const void* a, const void* b)
{
struct Edge* a1 = (struct Edge*)a;
struct Edge* b1 = (struct Edge*)b;
if (a1->weight > b1->weight) {
return a1->weight > b1->weight;
}
if (a1->weight < b1->weight) {
return a1->weight < b1->weight;
}
if (a1->weight == b1->weight) {
return a1->weight == b1->weight;
}
}
// The main function to construct MST using Kruskal's algorithm.
void KruskalMST(struct Graph* graph)
{
int V = graph->V;
struct Edge
result[V]; // Saves the resulting MST.
int e = 0; // An index variable, used for result[].
int i = 0; // An index variable, used for sorted edges.
// Step 1: Sort all the edges in non-decreasing order of their weight.
// If we are not allowed to change the given graph, we can create a copy of array of edges.
qsort(graph->edge, graph->E, sizeof(graph->edge[0]),
myComp);
// Allocate memory for creating V ssubsets.
struct subset* subsets
= (struct subset*)malloc(V * sizeof(struct subset));
// Create V subsets with single elements.
for (int v = 0; v < V; ++v) {
subsets[v].parent = v;
subsets[v].rank = 0;
}
// Number of edges to be taken is equal to V-1.
while (e < V - 1 && i < graph->E) {
// Step 2: Pick the smallest edge.
// And increment the index for next iteration.
struct Edge next_edge = graph->edge[i++];
int x = find(subsets, next_edge.src);
int y = find(subsets, next_edge.dest);
// If including this edge does't cause cycle,
// include it in result and increment the index
// of result for next edge.
if (x != y) {
result[e++] = next_edge;
Union(subsets, x, y);
}
// Else discard the next_edge.
}
int minimumCost = 0;
int nRoads = 0;
int nAirports = 0;
for (i = 0; i < e; ++i)
{
if (result[i].dest == 0) {
nAirports++;
} else {
nRoads++;
}
minimumCost += result[i].weight;
}
printf("Minimum Spanning Tree with minimal cost: %d\n",minimumCost);
printf("Number of airports: %d\n",nAirports);
printf("Number of roads: %d",nRoads);
return;
}
int main()
{
int v = 0; // Number of vertexes(cities) in the graph (includes the "sky" vertex).
int a = 0; // Number of airports.
int edges = 0; // Number of roads.
int e = 0; // Number Total number of edges in the graph.
int city = 0;
int airport = 0;
int city1 = 0;
int city2 = 0;
int cost = 0;
printf("Input the number of cities: \n");
scanf("%d", &v);
printf("Input the number of airports: \n");
scanf("%d", &a);
printf("Input the number of roads: \n");
scanf("%d", &e);
edges = a + e;
if (a > 0) {
v = v + 1;
}
struct Graph* graph = createGraph(v, edges);
for (int i = 0; i < a; i++) {
printf("Input the city and the building cost of the airport: \n");
scanf("%d %d", &city, &airport);
graph->edge[i].src = city;
graph->edge[i].dest = 0; // "sky" vertex.
graph->edge[i].weight = airport;
}
for (int j = a; j < edges; j++) {
printf("Input the cities and the cost of the road: \n");
scanf("%d %d %d", &city1, &city2, &cost);
if (a == 0) {
graph->edge[j].src = city1 - 1;
graph->edge[j].dest = city2 - 1;
graph->edge[j].weight = cost;
} else {
graph->edge[j].src = city1;
graph->edge[j].dest = city2;
graph->edge[j].weight = cost;
}
}
KruskalMST(graph);
return 0;
}
Example of a bug - 0 airports declared but still counts an airport:
Input the number of cities:
4
Input the number of airports:
0
Input the number of roads:
4
Input the cities and the cost of the road:
1 2 1
Input the cities and the cost of the road:
2 3 2
Input the cities and the cost of the road:
3 4 1
Input the cities and the cost of the road:
4 1 1
Minimum Spanning Tree with minimal cost: 3
Number of airports: 1
Number of roads: 2
The expected number of airports should be 0.

C Bubblesort in LinkedList

I'm trying to sort a doubly linked list, but I'm having some trouble. I'm a noob in C and I guess my problem is with pointers..
I just can't see how to swap two positions inside the list and so maybe that's the issue.
I tryied to sort it by using Bubblesort, even knowing that it's complexity is not so good because, how I'm still learning, thought that it was an easy way to start.
I also tryied reading some things about swaping elements in a linkedlist and how to sort them, but I'm really stuck with this problem...
PS: I started the for with the m->next cause my list has a header(m).
PS2:I'm getting the error "request for member ‘next’ in something not a structure or union", and don't know how to fix it
struct segment {
int x, y; /// position
char c; // letter
struct segment* next;
struct segment* prev;
};
void sortingSegments(struct segment* m) {
struct segment **j; struct segment **i;
for(i = &((m->next)->next); i !=NULL; i = i->next) {
for(j = &(m->next); j == i; j = j->next) {
if ((*j)->c > (*i)->c) {
struct segment **aux;
aux = i;
(*aux)->next = (*i)->next;
(*aux)->prev = (*i)->prev;
i = j;
(*i)->next = (*j)->next;
(*i)->prev = (*j)->prev;
j = aux;
(*j)->prev = (*aux)->prev;
(*j)->next = (*aux)->next;
}
}
}
}
Please read the comments and try to understand the linking of nodes.
It is based on the simple bubble sort described in wikipedia.
void sortingSegments(struct segment** m) {
struct segment *i, *tmp, *prev, *next;
int swapped = 1;
/*
* https://en.wikipedia.org/wiki/Bubble_sort#Pseudocode_implementation
* n = length(A)
* repeat
* swapped = false
* for i = 1 to n-1 inclusive do
* //if this pair is out of order
* if A[i - 1] > A[i] then
* // swap them and remember something changed
* swap(A[i - 1], A[i])
* swapped = true
* end if
* end for
* until not swapped
*/
// looping until no more swaps left
while (swapped) {
swapped = 0;
// we begin from the second item at each iteration
for (i = (*m)->next; i; i = i->next) {
// we need to swap i with i->prev
if (i->prev->c > i->c) {
prev = i->prev;
next = i->next;
// swapping first and second elements,
// so update m to reflect the change made
// to the head of the list
if (prev == *m) {
*m = i;
}
// so there is a prev of prev, update that two links
else {
prev->prev->next = i;
i->prev = prev->prev;
}
// so there is a next, update that two links
if (next) {
next->prev = prev;
prev->next = next;
}
// no next element, mark the end of the list
else {
prev->next = NULL;
}
// this is obvious, prev now becomes i's next
prev->prev = i;
i->next = prev;
// this is needed to reflect the change in i
i = prev;
swapped = 1;
}
}
}
}

a c program to add two singly linked lists, of unequal lengths containing single digited numbers in all of their nodes

i got this as an interview question. i was given 2 linked lists of unequal lengths,containing a single digited number in each of their nodes. i was asked to build a 3rd linked list which contains the sum of the two linked lists, again in the form of 1 digit in a node.
ex:
linked list 1 is
4-7-9-6
linked list 2 is
5-7
then the 3rd linked list would be
4-8-5-3
can someone suggest me an efficient algorithm, with minimum compromise in terms of space complexity?(i am not expecting an algo dat involves reversing the lists many times).
Reverse lists 1 and 2
Sum element-by-element (while
maintaining a carry), putting the
results in a list 3 that you
construct from tail to head
OR
Convert lists 1 and 2 to ints (e.g. int list1AsInt = 0; For each node {list1AsInt *= 10; list1AsInt += valueOfThisNode;} )
Sum those ints
Convert the result to a linked list (e.g. valueOfBrandNewNode = list3AsInt % 10; list3AsInt /= 10; Add a new node that points to the prev one; )
OR
Traverse both lists once to find out
their lengths. For this example,
let's assume that list 1 is longer
by N nodes.
Create a list 3 to represent the sum
without carries and a list 4 to
represent the carries.
For the first N nodes of list 1,
copy those values to list 3 and make
list 4's values be 0.
For the remaining nodes of lists 1
and 2, sum element-by-element,
putting the sum mod 10 in list 3 and
the carry in list 4. Keep track via
a bool of whether list 4 is all 0's.
Add a last node with value 0 to list
4.
If list 4 is entirely 0's, done.
Else, recurse to step 2,
treating list 3 as
the new list 1 and list 4 as the new
list 2. We know the length of the
new list 1 is the larger of the lengths
of the old lists 1 and 2, and the length
of the new list 2 is one more than that.
Read each digit as its ASCII equivalent into a char array indexed from 0, for both lists.
Use the atoi() function on both char arrays ( you may use atol() or atoll() if you are concerned about the length)
Add both numbers
Use the itoa() function to convert to a char array & then put back into new list.
Although, I admit the itoa() function is not standard.
If the lists are doubly linked it's easy:
Traverse both lists to the end.
Add the digits in corresponding nodes, and keep the carry digit.
Create the node in list 3.
Move one node towards the start of the lists and repeat.
The solution could be much simpler if the list stored the numbers in reverse order.
Nevertheless, with the given constraint, here is an approach.
find the nthToLast digit of both lists, starting with n = 0,
create a node with the sum of the digits,
update the (running) carry,
insert the newly created node at the head of the result list
Following is the (untested) C code.
typedef struct DigitNode_ {
int digit;
struct DigitNode_ * next;
} DigitNode;
/* Returns the n-th element from the end of the SLL;
if no such element exists, then return NULL.
See: https://stackoverflow.com/questions/2598348/
*/
extern DigitNode * nthNodeFromTail( DigitNode * listHead, size_t n );
/* Push pNode in the front, i.e. as the new head of the list */
extern void pushFront( DigitNode ** pListHead, DigitNode * pNode );
/* Create new list as sum of a and b, and return the head of the new list.
a -> 4 -> 7 -> 9 -> 6 -> NULL
b -> 5 -> 7 -> NULL
results in
c -> 4 -> 8 -> 5 -> 3 -> NULL
*/
DigitNode * sumDigitLists( DigitNode * a, DigitNode * b ) {
DigitNode * c = 0;
int carry = 0;
/* i is the position of a node from the tail of the list, backwards */
for( size_t i = 0; /* see 'break' inside */; i++ ) {
const DigitNode * const ithNodeA = nthNodeFromTail( a, i );
const DigitNode * const ithNodeB = nthNodeFromTail( b, i );
/* Stop when processing of both lists are finished */
if( !ithNodeA && !ithNodeB ) {
break;
}
const int ithDigitA = ithNodeA ? ithNodeA->digit : 0;
const int ithDigitB = ithNodeB ? ithNodeB->digit : 0;
assert( (0 <= ithDigitA) && (ithDigitA <= 9) );
assert( (0 <= ithDigitB) && (ithDigitB <= 9) );
const int conceptualIthDigitC = carry + ithDigitA + ithDigitB;
const int ithDigitC = conceptualIthDigitC % 10;
carry = conceptualIthDigitC / 10;
DigitNode ithNodeC = { ithDigitC, NULL };
pushFront( &c, &ithNodeC );
}
return c;
}
Take a look at this code:
node *add_two_linkedlist(node *head1,node *head2)
{
int i,j,temp;
node *p,*n;
p=head1;
n=head2;
i=count(head1);
j=count(head2);
if(i>j)
{
while(j!=0)
{
p->data=p->data+n->data;
if(p->data>10)
{
temp=(p->data)/10;
p->data=(p->data)%10;
p=p->next;
n=n->next;
p=p->data+temp;
j--;
}
}
return head1;
}
if(j>i)
{
while(i!=0)
{
n->data=p->data+n->data;
if(n->data>10)
{
temp=(n->data)/10;
n->data=(n->data)%10;
n=n->next;
p=p->next;
n=n->data+temp;
i--;
}
}
return head2;
}
}
This is straightforward. Assuming the leftmost node is the most significant bit. Align the two lists, add and propagate carry. Upon return create a new node if required..
#include <stdio.h>
struct list {
int val;
struct list * next;
};
int listadd (struct list *l1, struct list *l2) {
if ((l1 == NULL) || (l2 == NULL))
return;
int carry = 0;
if ((l1->next == NULL) && (l2->next != NULL)) {
carry += listadd (l1, l2->next) + l2->val;
return carry;
}
else if ((l1->next != NULL) && (l2->next == NULL)) {
carry +=listadd (l1->next, l2);
l1->val = l1->val + carry;
}
else if ((l1->next != NULL) && (l2->next != NULL)) {
carry += listadd (l1->next, l2->next);
}
else if ((l1->next == NULL) && (l2->next == NULL)) {
l1->val = l1->val + l2->val;
carry = l1->val/10;
l1->val = l1->val%10;
return carry;
}
carry = l1->val/10;
l1->val = l1->val%10;
return carry;
}
struct list * createnode (int val) {
struct list * temp = (struct list *) malloc (sizeof(struct list));
temp->val = val;
temp->next = NULL;
return temp;
}
int main() {
int carry = 0;
struct list *l1 = createnode(1);
l1->next = createnode(2);
struct list *l2 = createnode(7);
l2->next = createnode(8);
carry = listadd(l1,l2);
if (carry != 0) {
struct list * temp = createnode(carry);
temp->next = l1;
l1 = temp;
}
while (l1!= NULL) {
printf ("%d", l1->val);
l1=l1->next;
}
}

Resources