I'm having difficulties on making an array of linked lists. I have this struct
typedef struct node {
int id;
struct node * next;
} t_point;
t_point* array[10];
and I want, for example, that array[0] points to the head of a linked list, and then fill with, repeating this process to all spaces of the array
I understand how I need to code it, but I can't get it right. I just want someone to show me and explain me the syntax.
Something like this:
t_point* array[10]
void link_list()
{
int array_length = sizeof(array) / sizeof(t_point*);
// Allocate the memory for the first list item
array[0] = malloc(sizeof(t_point));
// Iterate through each item in `array` and allocate it some memory
for (int i = 1; i < array_length; i++)
{
// Allocate memory for the next item
array[i] = malloc(sizeof(t_point));
// Set the previous item's `next` field to the current item pointed to by `i`
array[i - 1]->next = array[i];
}
// Close the list by adding a NULL pointer
array[array_length - 1]->next = NULL;
}
Also remember to free the malloc'ed memory otherwise you will get memory leaks. I'll leave that up to you.
Related
I am struggling with the free of memory working with dynamic arrays. Considering the following code:
struct element{
float a;
float b;
};
struct list{
int size;
struct element *myelements;
};
int main(){
struct list mylist;
mylist.size = 0;
mylist.myelements = (struct element*) malloc(sizeof(struct element)*4); //I reserve it as if i had struct element myelements[4]
//i do stuff like
int i;
for(i = 0; i< 4 ; i++){
mylist.myelements[i].a = i;
mylist.myelements[i].b = i*2;
}
//I try to free myelements[2] for example, but i get an error
free(mylist.mylements[3]);
return 0;
}
My question is, how am i supposed to free the second possition of my array of elements. I have thought some alternatives involving realloc:
mylist.mybooks = realloc(mylist.mybooks, sizeof(mylist.mybooks) - sizeof(struct element));
but in that case wouldn´t I have to reorder the elements of the array?
Thanks in advance!
My question is, how am i supposed to free the second possition of my array of elements.
free deallocates the entire allocation done by malloc, it cannot deallocate a part of one allocation.
A common way to manage a resizeable array is to maintain its capacity and size, and when removing elements move subsequent array elements to fill the removed element gap and reduce the size. The spare capacity is used for new elements when they get inserted. Calling realloc for every element insertion/removal is sub-optimal in terms of speed.
I have a header class containing the following struct definitions:
struct Entry {
int key;
char *value;
};
typedef struct Entry Entry;
struct Heap {
int capacity;
int size;
Entry **elements;
};
typedef struct Heap Heap;
And, I'm trying to write a function makeHeap that "returns a pointer to some newly allocated Heap with the given capacity, a size of 0, and an elements array allocated with the given capacity."
The elements array is what I'm not entirely sure about. It's supposed to contain pointers (references) to Entry objects. Which I am not sure if I'm doing correctly here. In order to make an array that holds references to Entry objects, I declare a double pointer array (due to the Entry having a pointer in it) and then I initialize elements iteratively, and then set my newly created heap's elements pointer to a pointer of the **elements array I just built.
I'm not getting any compile errors, but I honestly don't know if I am doing this correctly. Any input would be greatly appreciated. I did some searches but couldn't find the case where a struct was defined quite in the way mine is with the double pointer array Entry** elements.
Also, as far the syntax between Entry** elements and Entry **elements are these interchangeable? As in they are both declaring an array that holds double pointers of type Entry?
Heap *makeHeap(int capacity) {
//Make the heap
Heap* theHeap = calloc(1, sizeof(Heap));
//set its capacity to param
theHeap->capacity = capacity;
//inital size is 0
theHeap->size = 0;
//elements contains pointers (references) to Entry objects.
Entry **elements[capacity];
//iterate capacity times allocating an entry reference for each element to be placed
int i = 0;
for (; i < capacity; i++) {
elements[i] = calloc(1, sizeof(Entry));
}
theHeap->elements = *elements;
return theHeap;
}
you'll need to malloc the elements of the heap as well, you can't just assign an array to it in a function as it will become invalid once the makeHeap() function exit. Here's your code with the correction:
Heap* makeHeap(int capacity) {
//Make the heap
Heap* theHeap = calloc(1, sizeof(Heap));
//set its capacity to param
theHeap->capacity = capacity;
//inital size is 0
theHeap->size = 0;
//elements contains pointers (references) to Entry objects.
theHeap->elements = calloc(capacity,sizeof(Heap*));
//iterate capacity times allocating an entry reference for each element to be placed
int i = 0;
for(; i < capacity; i++) {
theHeap->elements[i] = calloc(1, sizeof(Entry));
}
return theHeap;
}
Note: Make sure to free everything once you are done with it:
Heap* test = makeHeap(10);
//Do your stuff with the heap...
for(size_t i = 0;i<test->capacity;i++){
//Note: free the 'char* value' if you malloced them
free(test->elements[i]);
}
free(test->elements);
free(test);
You seem to have never allocated memory for elements of type Entry**. The position of the asterisks does NOT matter to answer that last question! They are declaring double pointers so really declaring 2D arrays or an array of Entry pointers, NOT "an array that holds double pointers of type Entry".
Entry** elements[capacity]; should be Entry** elements[capacity] = malloc(sizeof(Entry*) * capacity) as well.
I'm trying to create a linked list without using structures in C.
I want to be able to store an int variable on every node and a pointer to the next node, add unlimited numbers to the list, remove the first item, print all of the elements, etc.
I was thinking that every node of type int** should have 2 pointers of type int*.
the first one will point to an int address and the second will point to NULL.
Then, if I like to add a number to the list, I'll use the last pointer to point to a new allocated node of type int** and so on.
I'm having trouble writing the proper code for this though, and can't seem to reach to the actual int values. See the image below:
You can achieve this by allocating two uintptr_t each time: the first allocated memory space will be responsible for storing the value of the integer and the second one will be pointing to the next memory location.
uintptr_t nodeFirst = malloc(2 * sizeof(uintptr_t));
...
...
uintptr_t nodeNext = malloc(2 * sizeof(uintptr_t));
....
....
*nodeFirst = someIntValue;
*(nodeFirst + 1) = nodeNext;
...
The fact is, my solution above is still using the struct analogy, but w/o the struct keyword.
Here is a complete solution of a LinkedList managed as int ** pointers.
Step 1 - the addNode() function to add one node to the int **head.
int **addNode(int **head, int ival)
{
int **node = malloc(2 * sizeof(int *));
// don't forget to alloc memory to store the int value
node[0] = malloc(sizeof(int));
*(node[0]) = ival;
// next is pointing to NULL
node[1] = NULL;
if (head == NULL) {
// first node to be added
head = node;
}
else {
int **temp;
temp = head;
// temp[1] is the next
while (temp[1]!=NULL) {
// cast needed to go to the next node
temp = (int **)temp[1];
}
// cast needed to store the next node
temp[1] = (int *)node;
}
return (head);
}
Step 2 - a function display() to explore the current linkedlist.
void display(int **head)
{
int **temp;
int i = 0;
temp = head;
printf("display:\n");
while (temp!=NULL) {
// temp[0] is pointing to the ivalue
printf("node[%d]=%d\n",i++,*(temp[0]));
temp = (int **)temp[1];
}
printf("\n");
}
Step 3 - the popNode() function to remove the first node.
int **popNode(int **head)
{
int **temp;
if (head!=NULL) {
temp = (int **)head[1];
// don't forget to free ivalue
free(head[0]);
// then free the next pointer
free(head[1]);
head = temp;
}
return (head);
}
Step 4 - then an example of main() function using the linkedlist.
int main()
{
int **head = NULL;
head = addNode(head,111);
head = addNode(head,222);
head = addNode(head,333);
display(head);
// display:
// node[0]=111
// node[1]=222
// node[2]=333
head = popNode(head);
display(head);
// display:
// node[0]=222
// node[1]=333
while ((head = popNode(head))!=NULL);
display(head);
// display:
return (0);
}
Allocate two arrays, both of which are stored as pointers. In C, they can be the pointers you get back from calloc(). The first holds your node data. We can call it nodes. The second is an array of pointers (or integral offsets). We can call it nexts. Whenever you update the list, update nodes so that each nexts[i] links to the next node after the one that contains nodes[i], or an invalid value such as NULL or -1 if it is the tail. For a double-linked list, you’d need befores or to use the XOR trick. You’ll need a head pointer and some kind of indicator of which elements in your pool are unallocated, which could be something simple like a first free index, or something more complicated like a bitfield.
You would still need to wrap all this in a structure to get more than one linked list in your program, but that does give you one linked list using no data structure other than pointers.
This challenge is crazy, but a structure of arrays isn’t, and you might see a graph or a list of vertices stored in a somewhat similar way. You can allocate or deallocate your node pool all at once instead of in small chunks, it could be more efficient to use 32-bit offsets instead of 64-bit next pointers, and contiguous storage gets you locality of reference.
Im toying with creating my own hash table data structure, but I have hit an unexpected problem, which I can't solve and haven't found a satisfying solution for it yet.
See, I have this linked list struct
struct Link
{
int v;
struct Link* next;
}
and then inside the hash table structure I want keep track of an array linked lists, like this:
struct Link** entries;
What I run into is, that for this to work, I first have to initialize the array like this:
entries = malloc(sizeof(struct Link*) * N);
for (i = 0; i < N; i++)
entries[i] = malloc(sizeof(struct Link));
What I want is not having to do the for loop that initializes the structs, because that's not how linked lists work, I want to leave entries[x] blank until it actually gets assigned a value.
If I don't do the for loop this happens:
if (entries[x] != NULL) /* true, the array is initialized */
entries[x]->v = value; /* SEGFAULT, there is no struct initialized */
That if statement 'should' return false if I haven't assigned a Link struct to it yet, but it doesn't.
One way of solving this problem is to just initialize all the first links of the linked list with that for loop and then checking for the value, but that's not what I want.
So does anyone know a way to solve this the way I want it to?
You can use calloc rather than malloc while allocating entries like:
entries = calloc(sizeof(struct Link*), N);
Well, you can't. Uninitialized pointers are not necessarily NULL.
You will need to initialize the pointer array after you allocate space for it with malloc(). You can use another for-loop like:
for (i = 0; i < N; i++)
{
entries[i] = NULL;
}
or simply use calloc() to allocate the array. This will set all elements to 0.
entries = calloc(N, sizeof(struct Link*));
Afterwards you need to allocate the elements as needed:
if (entries[x] == NULL)
{
entries[x] = malloc(sizeof(struct Link));
}
entries[x]->v = value;
I am working on a project where I need to malloc some data. I am trying to reduce the heap peak of my program by changing around the main structure values I use. I am using a linked list. My struct is like:
struct myS{
int a,b;
float a,b;
struct myS *next;
};
I was thinking that instead of mallocing the struct pointer I would store it in a global array since I dont have much data. How would I do this ?
If you have upper bound for the number of elements you are going to need, you can create a global array [not dynamically allocated], let it be struct myS heap[], and an integer idx, initialized to 0. Once you allocate an element, you will need to increase idx, and attach this element to the requester.
Note - it is a good solution only if you are not expecting to delete elements [or you can afford to allocate each element only once].
If you do need delete, you will need to allocate an extra array that tells you which elements are currently in use, make idx circular [increase with idx = (idx + 1) % size], and check if each element is allocated before giving it, but as I say - it will probably be more time consuming!
code snap [not supporting deletes]:
struct myS heap[SIZE];
int idx = 0;
...
struct myS* allocate() {
return &(heap[idx++]);
}
Note: The above code snap is dangerous - it might overflow if you try to allocate more elements then you have in SIZE.
You could do something like this:
struct myS myArray[ARRAY_SIZE];
/* ... */
struct myS *head = &myArray[0];
head->next = &myArray[1];
head->next->next = &myArray[2];
/* etc... */
The array indexes used doesn't have to be sequential, e.g. head can be index 3 and head->next can be index 21
If you want to initialize the list to use all entries in the array at once, you could do it in a loop:
struct myS *node = head;
for (int i = 1; i < ARRAY_SIZE; i++)
{
node->next = &myArray[i];
node = &myArray[i];
}
node->next = NULL; /* Make sure the tail of the list doesn't have a 'next' pointer */