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 */
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'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.
I want to create tree with multiple children and create every node with a function. Here is my structure for node:
typedef struct node {
char *string; // Name of the node
int number_of_children;
struct node *children[];
} node;
And here is my function to create new node (with four children):
node *add_node(char *string, node *left, node *middle_left, node *middle_right, node *right) {
node *p;
if ((p = malloc(sizeof(node))) == NULL) yyerror("Memory error");
p->string = strdup(string);
p->children[p->number_of_children] = left;
p->children[p->number_of_children + 1] = middle_left;
p->children[p->number_of_children + 2] = middle_right;
p->children[p->number_of_children + 3] = right;
p->number_of_children = 4;
return p;
}
When I run this function value under p->string is changed to some garbage. When I wanted to set fixed number of children (in the structure I changed struct node *children[] to struct node *children[4]) I get segmentation fault. Do you have any ideas?
The way you define your struct, you must know how many children you can have beforehand, because you have to allocate the memory for the last member explicitly:
node *p = malloc(sizeof(node) + nchildren * sizeof(node));
You could reallocate to accomodate more nodes later, but this isn't a feasible approach here, because the handle to the reallocated memory might change, which will break the tree connectivity.
There are better approaches to have nodes with a varying number of children, for example:
Settle on a fixed maximum number of children, maybe 4, and make the member array children explicitly 4 elements long. Keep a number that tells you how many children are valid.
Make the list of children a dynamically allocated array that you can reallocate later. This means you have a two-level allocation: First thze node proper, then a list of its children.
Keep a linked list of child nodes. Come to think of it, you could rearrange the tree so that each node has a child for its oldest child node and a sibling node fo the next oldest sibling of each node.
I'm not sure what you want to do exactly, but the first approach seems to be the simplest for your concerns.
Your code has several other errors:
You should only allocate memory when you create a node. Obviously, you already pass in valid node handles to your function. These nodes have already memory allocated to them or they are NULL. The following:
p = malloc(sizeof(*p));
p = pref;
will allocate memory and immediately lose the only handle to that memory, which is a memory leak. You don't need to allocate here, just say p = pref.
The memory allocated with malloc isn't initialised; it contains garbage. Initialise all struct members before you use them. Alternatively, consider using calloc, which allocates and zeroes out the memory.
Combined assignments and checks as in if ((p = malloc(sizeof(node))) == NULL) are valid, but complicated to read. In my opinion, they are better separated into assignment and subsequent check. (After all, it just saves you typing p twice at the cost of some extra parantheses.)
An example where you pass in a variable number of chilödren by array might look like this:
typedef struct node {
char *string;
size_t number_of_children;
struct node *children[4];
} node;
node *add_node(char *string, node *child[], size_t n)
{
node *p = malloc(sizeof(*p));
size_t i;
if (p == NULL) yyerror("Memory error");
p->string = strdup(string);
for (i = 0; i < n; i++) p->children[i] = child[i];
p->number_of_children = n;
return p;
}
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.
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;