How to access array linked lists on heap? - c

I am having a problem accessing an subarray of a node. I have two structs written where one contains the other. I'm not able to access the beyond the first node of the subarray.
struct node{
int distance;
int destination;
int weight;
node *adj;
};
struct adjList{
struct node *node;
adjList *array;
};// adjList a is made out of an array of "nodes". Essentially each element in the adjList a should have a pointer to a subarray of "nodes" that i can access.
a=(adjList*) malloc(numOfNodes * sizeof(struct adjList));//allocate space for array of linked lists
for(int j=0; j<numOfNodes; j++){
array[j].node=malloc(numOfEdges * sizeof(struct node));//allocate space for each linked list in the array
}
for(int j=0; j<numOfNodes; j++){
a[j].node->adj[j]=NULL; //trying to set the "jth's" element of the adjacencylist's "jth" node. This syntax does not work as the compiler wont let me even use it.
}
My whole goal here is to have an array of linked lists. Not sure why this method isnt working.

To have array of linked list, you need to create an array of pointers to the first node of linked lists.
struct node **array = malloc(sizeof(struct node*) * arraySize /* numOfNodes */);
Now array[i] will be pointing to ith linked list.
for(int i=0; i<arraySize ; i++){
struct node *head = NULL;
/* Allocate nodes for ith linked list */
for(int j=0; j<numOfNodes; j++) {
if(0 == j) {
array[i] = malloc(sizeof(struct node)); //First node of ith linked list
memset(array[i], 0, sizeof(struct node)); //OR you can use calloc. Required to remove junk pointers in node.
head = array[i];
} else {
head->adj = malloc(sizeof(struct node)); /* Allocate jth node */
memset(head->adj, 0, sizeof(struct node)); //OR you can use calloc. Required to remove junk pointers in node.
head = head->adj;
}
}
}
You can traverse ith linked list as below.
struct node *head = array[i];
while(head) {
printf("\ndist %d dest %d weight %d\n", head->distance, head->destination, head->weight);
head = head->adj;
}

You should read the man page malloc(3), in particular the calloc() part.
It is not enough to just put a pointer into a struct and assume that magically there will be an array. You have to reserve memory for it by using the functions described in that man page. And more importantly you have to free() the reserved memory, when you don't need it anymore.
Also you should consider making the length of your array part of your struct.
Like so:
struct node{
int distance;
int destination;
int weight;
node *adj;
size_t adj_count;
};
struct adjList{
struct node *node;
size_t node_count;
adjList *next; // I renamed this member to next,
// which makes it more clear that this is a linked list
};
EDIT: After you edited your question, there is suddenly a malloc(), but it is most certainly wrong. Or your naming of your data structures is very misleading.

Related

i am having problems understanding this code, can someone help me explicitly explain it, expecially " while (size--) & tmp = (int *)&node->n;"

#include <stdio.h>
#include <stdlib.h>
/**
* struct listint_s - Doubly linked list node
*
* #n: Integer stored in the node
* #prev: Pointer to the previous element of the list
* #next: Pointer to the next element of the list
*/
typedef struct listint_s // generating a structure
{
const int n;
struct listint_s *prev;
struct listint_s *next;
} listint_t;
/**
* create_listint - Creates a doubly linked list from an array of integers
*
* #array: Array to convert to a doubly linked list
* #size: Size of the array
*
* Return: Pointer to the first element of the created list. NULL on failure
*/
listint_t *create_listint(const int *array, size_t size)
{
listint_t *list;
listint_t *node;
int *tmp;
list = NULL;
while (size--)
{
node = malloc(sizeof(*node));
if (!node)
return (NULL);
tmp = (int *)&node->n;
*tmp = array[size];
node->next = list;
node->prev = NULL;
list = node;
if (list->next)
list->next->prev = list;
}
return (list);
}
I am having difficulty understanding these lines of code
while (size--)
and
tmp = (int *)&node->n;
When will the code exit the while loop, also i really want to understand how this piece of code works.
Within the structure
typedef struct listint_s // generating a structure
{
const int n;
struct listint_s *prev;
struct listint_s *next;
} listint_t;
the data member n is declared with the qualifier const. So you may not directly assign to it a value like for example
node->n = array[size];
The compiler will issue an error saying that you are trying to change a constant object.
So there is used a trick. At first there is declared a pointer to the object as a pointer to a non-constant object
int *tmp;
and this pointer is assigned with the address of the data member node->n using casting
tmp = (int *)&node->n;
The casting is required because the expression &node->n has the type const int *
And then using the pointer tmp a value is assigned to the constant object
*tmp = array[size];
As for this while loop
while (size--)
the it iterates while the number of elements in the array is not equal to 0. You may rewrite the while loop like
while ( size-- != 0 )
The function adds new elements in the beginning of the list storing in it values of the passed array starting from the last element of the array and down to the first element of the array. .
Pay attention to that the function is unsafe. It can produce memory leaks if some node will not be dynamically allocated due to this if statement
node = malloc(sizeof(*node));
if (!node)
return (NULL);

Why do I need double pointers?

I don't understand why I need double pointers inside 'struct graph'. Is it because it allows me to access one of the nodes that I made inside the function makeGraph()?
If I use one pointer (struct node *adjList) then I can't set the nodes to NULL that I made inside makeGraph().
I got the code frome programiz.com and in the article that explains this code it says: Don't let the struct node** adjList overwhelm you. All we are saying is we want to store a pointer to struct node*. This is because we don't know how many vertices the graph will have and so we cannot create an array of Linked Lists at compile time.
If I do: graph->adjList[1] does it go to the address of the second node or goes it inside the node? (I'm talking about the nodes that I create inside makeGraph())
I understand the rest of the code. If anyone can help me it would be appreciated.
#include <stdlib.h>
#include <stdio.h>
struct node
{
int vertex;
struct node *next;
};
struct graph
{
int numVertices;
struct node **adjList; // <--- THIS ONE
};
struct graph *makeGraph(int vertices) // Creating a Graph
{
struct graph *graph = malloc(sizeof(struct graph));
graph->numVertices = vertices;
graph->adjList = malloc(sizeof(struct node) * vertices); // creating the nodes
for (int i = 0; i < vertices; i++)
graph->adjList[i] = NULL; // Setting all nodes to NULL
return graph;
}
void addEdge(struct graph *graph, int src, int dest) // Add Edge
{
struct node *newNode = makeNode(dest);
newNode->next = graph->adjList[src];
graph->adjList[src] = newNode;
struct node *newNode2 = makeNode(src);
newNode2->next = graph->adjList[dest];
graph->adjList[dest] = newNode2;
return;
int main()
{
struct graph *graph1 = makeGraph(4);
addEdge(graph1, 0, 1);
addEdge(graph1, 0, 2);
addEdge(graph1, 0, 3);
}
An adjacency list is being represented as a linked list of struct node. The list is accessed by a pointer to the first element of the list. (The pointer will be NULL when the list is empty.) The pointer has type struct node *.
The graph has a number of vertices as set in the numVertices member of struct graph. Each vertex needs an adjacency list, and each adjacency list needs a struct node *. So the graph needs an array of struct node * of length numVertices. The authors of the code chose to allocate the array dynamically as a separate memory block pointed to by the adjList member. The type of the adjList member is a pointer to the element type. The element type is struct node * so the type of the adjList member is struct node **.
There is another way to allocate the memory for the struct graph and its adjacency list. They could be allocated as single block by changing the adjList member to be a flexible array member, as shown below:
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
struct node
{
int vertex;
struct node *next;
};
struct graph
{
int numVertices;
struct node *adjList[]; // <--- FLEXIBLE ARRAY MEMBER
};
struct graph *makeGraph(int vertices) // Creating a Graph
{
struct graph *graph = malloc(offsetof(struct graph, adjList[vertices]));
graph->numVertices = vertices;
for (int i = 0; i < vertices; i++)
graph->adjList[i] = NULL; // Setting all nodes to NULL
return graph;
}
offsetof(struct graph, adjList[vertices]) is the offset in bytes from the address of a struct graph to the address of the adjList[vertices] array member element. Allocating a block of memory of that size is just large enough to hold a struct graph plus the array of pointers. Another way to specify the size is sizeof(struct graph) + vertices * sizeof(struct node *) or alternatively sizeof(struct graph) + vertices * sizeof(graph->adjList[0]), but I think using the offsetof macro is a more succinct way to specify the size.

C: From char array to linked list

I'm still learning how to program in C and I've stumbled across a problem.
Using a char array, I need to create a linked list, but I don't know how to do it. I've searched online, but it seems very confusing. The char array is something like this char arr[3][2]={"1A","2B","3C"};
Have a look at this code below. It uses a Node struct and you can see how we iterate through the list, creating nodes, allocating memory, and adding them to the linked list. It is based of this GeeksForGeeks article, with a few modifications. I reccommend you compare the two to help understand what is going on.
#include <stdio.h>
#include <stdlib.h>
struct Node {
char value[2];
struct Node * next;
};
int main() {
char arr[3][2] = {"1A","2B","3C"};
struct Node * linked_list = NULL;
// Iterate over array
// We calculate the size of the array by using sizeof the whole array and dividing it by the sizeof the first element of the array
for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) {
// We create a new node
struct Node * new_node = (struct Node *)malloc(sizeof(struct Node));
// Assign the value, you can't assign arrays so we do each char individually or use strcpy
new_node->value[0] = arr[i][0];
new_node->value[1] = arr[i][1];
// Set next node to NULL
new_node->next = NULL;
if (linked_list == NULL) {
// If the linked_list is empty, this is the first node, add it to the front
linked_list = new_node;
continue;
}
// Find the last node (where next is NULL) and set the next value to the newly created node
struct Node * last = linked_list;
while (last->next != NULL) {
last = last->next;
}
last->next = new_node;
}
// Iterate through our linked list printing each value
struct Node * pointer = linked_list;
while (pointer != NULL) {
printf("%s\n", pointer->value);
pointer = pointer->next;
}
return 0;
}
There are a few things the above code is missing, like checking if each malloc is successful, and freeing the allocated memory afterwards. This is only meant to give you something to build off of!

meaning of a struct within a struct in c [duplicate]

This question already has answers here:
What is self-referencing structure in C?
(3 answers)
Closed 3 years ago.
Can someone explain what we mean when we do, like what does struct Node* next do. does it create a pointer of type struct? any help and resources about structures in c would be helpful
struct Node {
int dest;
struct Node* next;
};
"struct" itself is not a type. "struct [tag]" is a type, for example "struct Node" in your code.
In your case you define a structure type. Every structure of that type will contain a pointer to another structure of that type as a member called "next".
This allows you to chain the structures together in a so called linked list. You store a pointer to the first structure in a variable, then you can follow the chain of links down to the structure you need.
For example, you can do
struct Node *start;
start = malloc(sizeof struct Node);
start->dest = 7;
start->next = malloc(sizeof struct Node);
start->next->dest = 13;
start->next->next = malloc(sizeof struct Node);
start->next->next->dest = 19;
printf("%d %d %d\n", start->dest, start->next->dest, start->next->next->dest);
free(start->next->next);
free(start->next);
free(start);
Please note that this code omits all error handling, in real code you have to handle the case when malloc returns NULL.
Also, in real code you would use such a structure in loops that traverse the chain, not directly as above.
As #Serge is pointing out in comments, is not a struct within a struct, is a reference (a pointer) to an object of the same type, an example:
#include <stdio.h>
struct Node {
int dest;
struct Node* next;
};
int main(void)
{
/* An array of nodes */
struct Node nodes[] = {
{1, &nodes[1]}, // next points to the next element
{2, &nodes[2]}, // next points to the next element
{3, NULL} // next points to null
};
/* A pointer to the first element of the array */
struct Node *node = nodes;
while (node) {
printf("%d\n", node->dest);
node = node->next; // node moves to the next element
}
return 0;
}
Output:
1
2
3
Of course, in my example there is no benefit in using a linked list, linked lists are useful when we don't know the number of elements before-hand.
Another example using dynamic memory:
struct Node *head, *node;
node = head = calloc(1, sizeof *node);
node->dest = 1;
while (more_elements_needed) {
node->next = calloc(1, sizeof *node);
node->next->dest = node->dest + 1;
node = node->next;
}
for (node = head; node != NULL; node = node->next) {
printf("%d\n", node->dest);
}

Printing Int in struct prints address

I'm reading an algorithms book and I found myself stuck on this bit. I create a doubly linked list and when I try to print out its contents it prints out what I believe is address or some other value that is not relevant to what I want. Here is the code:
typedef struct double_element *dElement;
struct double_element
{
int value;
dElement prev;
dElement next;
};
dElement createNewDListWithElements(int count)
{
dElement element = malloc(sizeof(dElement));
element->value = 1;
element->next = NULL;
element->prev = NULL;
dElement previous = element;
for (int i = 1; i < count; i++) {
dElement el = malloc(sizeof(dElement));
el->value = i;
el->next = NULL;
el->prev = previous;
previous->next = el;
previous = el;
}
return element;
}
void printDList(dElement node)
{
printf("printing doubly linked list:\n");
while (node) {
printf("%i\n", node->value);
node = node->next;
}
printf("end printing double linked list\n");
}
Here is the output:
printing doubly linked list:
1
1070320
1070336
1070352
1070368
1070384
1070400
1070416
1070432
1070448
end printing double linked list
Your problem is that you are trying to allocate space for a struct double_element, but you only ask for enough space to store a struct double_element*.
The problem is that you are allocating space for a pointer instead of the struct itself, the reason the dangerous typedef of the pointer, if you want to guarantee the allocation is correct regardless of the typedef's in your code you can do this
dElement element = malloc(sizeof(*element));
that would allocate space for the struct, just as if you had called
dElement element = malloc(sizeof(struct double_element));
you can see that the typedef is harmful, a pointer should be explicitly a pointer, so the correct way to write the code without falling in this kind of issue is
struct double_element *element = malloc(sizeof(struct double_element));
/* ^ don't skip this no matter what */
also, you should make clear what the struct names are and how you name your variables, you could for example use CamelCase for the struct names, and lower case with underscores for your variables, something like this
struct DoubleElement *element = ...
it would make it clear that DoubleElement is the name of a struct, and even though you can leave the struct instead of tyepdefing it, because that makes it even clearer.

Resources