Why the nodes in a linked list are declared as pointers? Nodes contains the pointer part in it to link to another node. Then why the nodes are itself a pointer?
struct node
{
int data;
struct node *link;
} *start;
Now we introduce nodes as
struct node *tmp;
Now this is a node which is a pointer to data type struct node..but for linking we use the link pointer to link the other node Why dindnt we coded node as
struct node tmp;
only...is this because of allocating dynamic memory..or something more?
Nodes in linked lists in C always allocated in a heap to allow you manage their lifetime. Therefore for creating, destroying and adding nodes to list, you need to declare a pointer on a node:
struct node *tmp; // declaring
tmp = (node*) malloc(sizeof(node)); // creating (allocating memory)
// ... tmp initializing and processing
free(tmp); // removing (freeing memory)
tmp = NULL;
Otherwise, if you create a node on stack node tmp;, it's lifetime will be managed by the rules of language, not by your business logic.
Related
I've created a doubly linked list, filled it with values and now I want to delete it and remove all the values to avoid memory leaks. Here's what I wrote as well as the structs that were used when creating the doubly linked list. Both those functions will be called towards the end of the main function.
struct node
{
struct node *next;
struct node *prev;
char *value;
};
// The type for a list.
typedef struct list
{
struct node head;
} List;
// The type for a list position.
typedef struct list_pos
{
struct node *node;
} ListPos;
void list_destroy(List *lst)
{
List p,q;
p = *lst;
while (p)
{
q = p.head->next;
free(p);
p = q;
}
*lst = NULL;
}
// Remove the value at the position and return the position of the next element.
ListPos list_remove(ListPos pos)
{
}
You appear to have the right general idea: you walk the list and free each node, making sure to grab any needed data from each node (in particular, the pointer to the next node) while the node holding it still exists. Your case differs from some that you might have seen, however, because instead of handling the overall list via a bare pointer to the head node, you have a separate object, of a separate type (List / struct list), to represent the list itself. This approach has much to recommend it, including, especially, the use of (apparently) a dummy head node, which provides for a variety of algorithmic simplifications. This is usually how I write a linked list.
But because struct list is not struct node, you cannot set a list pointer equal to a node pointer. Instead, create a struct node * to track your position. The first node to free would be the one referenced by struct node *to_free = lst->head.next, and the one after that would be the one referenced by to_free->next.
Note that you might need to free the struct list, too.
I have a linked list struct on me, and I used a node struct to help me store data and know where each node is pointing to. In the creation of my list, I did this:
struct list {
struct node *Head;
struct node *Tail;
}
struct node{
int val;
struct node * next;
}
struct list create_list(){
struct list new_list;
new_list = malloc(sizeof(struct list));
}
Then, when I am trying to free the list that I malloced for, I did this
void free_list(struct list linked_list){
free(linked_list);
}
However, I realize that I may have malloced wrong, because when you malloc, you need to assign it to a pointer. When I want to free the linked_list that I originally malloced for, nothing really changes.
I think this may be because the linked_list that I sent into free() is not a pointer, thus no changes have been made. I tried adding & and * to it, but I end up getting errors....
Any tips or help is appreciated.
Edit:
Fixed Typo on the struct list.
This is hw, so I cannot change the parameters of the functions, which is what is giving me a hard time freeing the linked list I made. This is because the function free_list() cannot change its parameter into a pointer linked list, so I don't know exactly what to do.
I will also take note of when I am mallocing for the linked list in the create_list function.
Yay for passing the linked list around by value rather than on the heap for something that small.
Is this more like what you want:
struct list create_list(){
struct list new_list = { NULL, NULL };
return list;
}
void free_list(struct list linked_list){
struct node *next;
for (struct node *node = linked_list.Head; node; node = next;)
{
temp = node->next;
free(node);
}
}
Thus freeing only the list nodes that were allocated with malloc().
In creating a linked list we make a node structure and it consists of both data and a pointer to the next node. Later when we make a function to append elements onto the linked list, we make a temporary node to store the inputted data.
Let’s consider the following program-
#include<stdio.h>
struct node
{
int data;
struct node* link;
}
struct node* root=NULL;
void main(append)
{
struct node* temp;
temp= (struct node*)malloc(sizeof(struct node))
.....
}
My first question set:
In line 11, why do we need to mention (struct node*) before the malloc function?
What is the significance of that?
My second question set:
If we are making a doubly linked list which would have a node structure consisting of 2 pointers (for next and previous node), would we also initialize a pointer (for traversing the list) of the struct node type?
Is there a different way to initialize the pointer in that case?
The significance is to make bugs in your program,
The malloc will return void* and when you assign to your struct somthing* it will convert automaticlly.
You simply don't cast the result of malloc as it returns void* . There is one fine explanation here
A better solution might be :
struct node *temp;
temp = malloc(sizeof *temp);
why do we need to mention '(struct node*)' before the malloc function,
what is the significance of that?
By writing (struct node*) before the malloc function, you are type-casting the return value to the specified type. The cast here is optional and often frowned upon.
if we are making a doubly linked list which would have a node
structure consisting of 2 pointers(...
When making a doubly linked list, you should declare something like:
struct node {
int data;
struct node *next;
struct node *previous;
};
You can allocate space for a node by using the malloc function. The next and previous pointers are again pointers to struct nodes. Call malloc again to allocate space for the next element. For the first node, the previous should be NULL and for the last node, next should be NULL. Here is one implementation.
This is the because the return type of malloc is void*. (struct node*) is a cast using which you tell the compiler that you want to treat the value returned by malloc as a pointer to struct node.
For double linked list you can use,
struct node
{
int data;
struct node *next,*prev;
};
int main()
{
struct node *new_node=(struct node *)malloc(sizeof(node));
}
malloc returns the void pointer(can be checked and verified at the header ), and so the type casting is necessary while assigning it to the other type of variable.
Request you to read at the link https://www.tutorialspoint.com/cprogramming/c_type_casting.htm
Why the nodes in a linked list are declared as pointers? Nodes contains the pointer part in it to link to another node. Then why the nodes are itself a pointer?
struct node
{
int data;
struct node *link;
} *start;
Now we introduce nodes as
struct node *tmp;
Now this is a node which is a pointer to data type struct node..but for linking we use the link pointer to link the other node
Why dindnt we coded node as
struct node tmp;
only...is this because of allocating dynamic memory..or something more?
Yes, this is because the nodes are allocated dynamically.
struct node tmp could be using tmp as a dummy or sentinel node, where it's data is not used, only it's next pointer to the actual first node of a list.
struct node *tmp would be using tmp as a pointer to the first node of a list or as a working pointer to some node in a list when scanning a list.
In some cases a list structure is also used:
struct list{
struct node *head // pointer to first node
struct node *tail // optional: pointer to last node
size_t size; // optional: number of items in a list
}
A circular list could be implemented using just a tail pointer to the last node, which in turn would have a next pointer to the head/first node.
Hi guys I'm new to linked lists, but I'm pretty sure that I know how they work, theoretically, I think I might having a syntax misunderstanding, or memory management error.
edit: My main purpose is to make a collection of lists which are indexed by the array, each array element is a head(or root) node. I'm having issues allocation dynamically this struct array.
What I'm doing is the following:
typedef struct item_list{
int item_name;
int item_supplier;
int item_price;
struct item_list *next
}node;
int i;
node ** shop_1 = (node **)malloc(shop_items_elements * sizeof(node));
for (i=0;i<=shop_items_elements;i++)
{
shop_1[i]->next=NULL;
}
I'm getting a segmentation fault while I try to give next at the element i the value of NULL.
The problem is that you are trying to allocate the memory for 20000 items as a contiguous block. Which implies that you actually haven't understood linked lists yet.
I think you are mixing up random access array functionality with pure linked lists which do not allow accessing individual items without traversing the list.
A linked list usually has a head and tail node which are initially NULL when there are no elements in the list:
node* head = NULL;
node* tail = NULL;
When adding a new node you first allocate it by using malloc with the size of a single node struct:
node* the_new_node = (node*)malloc(sizeof(node));
Initialize the struct members, specifically set next to NULL for each new node. Then use this append_node() function to append the node to the linked list:
void append_node(node** head, node** tail, node* the_new_node)
{
if(*tail == NULL)
{ // list was empty
*head = *tail = the_new_node;
}
else
{
(*tail)->next = the_new_node; // link previous tail node with new one
*tail = the_new_node; // set the tail pointer to the new node
}
Please note the pointer to pointers which are needed to update the head and tail pointers. Call the function like this for any given n you want to add:
append_node(&head, &tail, n);
Repeat this for every new node.
A much better way of encapsulating a linked list is putting the head and tail pointers into another struct
typedef struct linked_list
{
node* head;
node* tail;
} list;
and using an instance of that as first argument to append_node() (which I'll leave to you as an exercise ;)
When using such a linked list it is not possible to conveniently access the Nth node in less than O(n) since you have to follow all next pointers starting from the head node until you arrive at the Nth node.
EDIT: If you want to have the possibility to index the shop items and build a linked list from each of the elements I would suggest the following solution:
node** shop_1 = (node**)malloc(shop_items_elements * sizeof(node*));
int i;
for(i = 0; i < shop_items_elements; ++i)
{
node* n = (node*)malloc(sizeof(node));
n->next = NULL;
shop_1[i] = n;
}
You first allocate an array of pointers to node pointers which have to be allocated individually of course. Take a look at this diagram for reference:
The actual node instances may be larger than a pointer's size (unlike drawn in the diagram) which is the reason why you allocate N * sizeof(node*) in a block instead of N * sizeof(node).
Your code needs to look like this
int i;
node * shop_1 = (node *)malloc(shop_items_elements * sizeof(node));
for (i=0;i<shop_items_elements;++i)
{
shop_1[i].next=NULL;
}
Your malloc statement has allocated an array of nodes, not an array of pointers to nodes. (If that is what you wanted instead, then you would have had to initialize each pointer with a further malloc call before trying to assign a value to a field within the node pointed to.)