I am learning C and I've come up with a conceptual question about pointers.
Here is a simple code to push (add to the beginning) an int to a linked list in C.
The following code works:
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int val;
struct node *next;
} node_t;
void push(node_t **head, int val) {
// head is a pointer to the pointer of the first node_t
node_t *new_node; // new pointer to a node
new_node = (node_t *)malloc(sizeof(node_t));
new_node->val = val;
new_node->next = *head;
*head = new_node;
}
int main() {
// creating the first node
node_t *head;
head = (node_t *)malloc(sizeof(node_t));
head->val = 2;
head->next = NULL;
// pushing a value
push(&head, 1); // the '&' is important
return 0;
}
As you notice, we have to pass &head as a parameter. So I though changing the function so I could pass head instead. Here's the modified function :
void push(node_t *head, int val) {
node_t **p_head;
p_head = &head; // p_head is a pointer to the pointer of the first node_t
node_t *new_node; // pointer to a new node
new_node = (node_t *)malloc(sizeof(node_t));
new_node->val = val;
new_node->next = *p_head;
*p_head = new_node;
}
Why does this version won't work ?
Thanks in advance.
You should be able to pass along the structure's pointer for the creation of another structure in a linked list. I would suggest looking at the linked list structure in a slightly different way.
Usually, in the creation of a linked list, whenever a new list item (aka structure in your case) is created, the "next node structure" pointer is set to null and the previous linked list member has its "next node structure" pointer updated to the pointer of the newly created structure. Making some revisions to your program I store some additional information in your structure and produce a linked list of ten members. Following is the revised code.
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int val;
struct node *previous; /* Added this to use with the passed node pointer */
struct node *next;
} node_t;
node_t * push(node_t *nd, int val) /* Return the pointer of the newly created node */
{
node_t *new_node; // New pointer to a node
new_node = (node_t *)malloc(sizeof(node_t));
new_node->val = val;
new_node->previous = nd;
new_node->next = NULL;
return new_node;
}
int main()
{
node_t *work; // Pointer work variable for building a linked list of nodes
node_t *head;
head = (node_t *)malloc(sizeof(node_t));
head->val = 2; /* This value will get adjusted to provide unique values */
head->previous = NULL;
// Create a set of ten nodes.
work = head;
for (int i = 0; i < 10; i++)
{
work->next = push(work, (2 * i + i + 12));
work = work->next; /* Links this node to the newly created node. */
}
// Now travel down the chain and print out the pertinent statistics of the nodes.
work = head;
while (1)
{
printf("This node's values are: this->%p value->%d previous->%p next->%p.\n", work, work->val, work->previous, work->next);
if (work->next == NULL) /* We have reached the end of the list */
break;
work = work->next;
}
return 0;
}
When I ran this program, I received the following output on my terminal.
This node's values are: this->0x55bfd6edc2a0 value->2 previous->(nil) next->0x55bfd6edc2c0.
This node's values are: this->0x55bfd6edc2c0 value->12 previous->0x55bfd6edc2a0 next->0x55bfd6edc2e0.
This node's values are: this->0x55bfd6edc2e0 value->15 previous->0x55bfd6edc2c0 next->0x55bfd6edc300.
This node's values are: this->0x55bfd6edc300 value->18 previous->0x55bfd6edc2e0 next->0x55bfd6edc320.
This node's values are: this->0x55bfd6edc320 value->21 previous->0x55bfd6edc300 next->0x55bfd6edc340.
This node's values are: this->0x55bfd6edc340 value->24 previous->0x55bfd6edc320 next->0x55bfd6edc360.
This node's values are: this->0x55bfd6edc360 value->27 previous->0x55bfd6edc340 next->0x55bfd6edc380.
This node's values are: this->0x55bfd6edc380 value->30 previous->0x55bfd6edc360 next->0x55bfd6edc3a0.
This node's values are: this->0x55bfd6edc3a0 value->33 previous->0x55bfd6edc380 next->0x55bfd6edc3c0.
This node's values are: this->0x55bfd6edc3c0 value->36 previous->0x55bfd6edc3a0 next->0x55bfd6edc3e0.
This node's values are: this->0x55bfd6edc3e0 value->39 previous->0x55bfd6edc3c0 next->(nil).
Hopefully, this might give you some food for thought on pointer usage as it pertains to linked lists. Also, since the program is using "malloc" it usually is a good idea to have some cleanup in the program to make sure the memory is freed up (e.g. use the "free()" function).
Hope that helps.
Regards.
Related
I had this exercice that asks me to create a function that adds a number in a new node to the head of a linked list based on a struct containing one integer. This is the struct:
struct Node
{
int data;
struct Node *next;
};
no problem till now. so I created one that takes 2 arguments: the integer to add and the pointer to the head of linked list, but it didn't work. this is my code:
void push(struct Node* head, int new_data)
{
struct Node* new_node = (struct Node*) malloc(sizeof(struct Node));
new_node->data = new_data;
new_node->next = head;
head = new_node;
}
So, what I did is that I made the new_node point to the same node pointed by head, after that I make the new node the new head of the linked list. it seems very logical, although it didn't work. on the other hand, when I give the function the adress of head pointer instead of the pointer itself, it does work:
void push(struct Node** head_ref, int new_data)
{
/* 1. allocate node */
struct Node* new_node = (struct Node*) malloc(sizeof(struct Node));
/* 2. put in the data */
new_node->data = new_data;
/* 3. Make next of new node as head */
new_node->next = (*head_ref);
/* 4. move the head to point to the new node */
(*head_ref) = new_node;
}
and this is the main for the function with double **:
int main()
{
struct Node* head = NULL;
push(&head,7);
push(&head,6);
push(&head,3);
return 0;
}
I understand that the second function should work, but I don't see why it is necessary to use the adress of head and not head itself. I would be glad if anybody could explain the reason to me, Thanks.
but I don't see why it is necessary to use the adress of head and not head itself.
In plain c code you can't have references (as in contrast to c++), but just pointers.
The value stored in the head pointer variable should be changed from within the call to push(), so you need to pass the address of the head variable to change the (single * pointer) value.
int main()
{
struct Node* head = NULL;
push(&head,7);
// ...
}
void push(struct Node** head_ref, int new_data)
{
// ...
/* 3. Make next of new node as head */
new_node->next = (*head_ref); // Dereferencing head_ref yields the current
// content of head
/* 4. move the head to point to the new node */
(*head_ref) = new_node; // Store the newly allocated memory address
// into the head pointer
}
As you were tagging your question c++ originally this isn't necessary using c++ code.
You can take the pointer parameter by reference as well:
void push(struct Node*& head_ref, int new_data)
// ^
{
// ...
/* 3. Make next of new node as head */
new_node->next = head_ref;
/* 4. move the head to point to the new node */
head_ref = new_node; // <<<<<<<<<<
}
int main() {
struct Node* head = nullptr;
push(head,7);
push(head,6);
push(head,3);
return 0;
}
In the C program I've attached, I've defined a separate function called push() to add a node to the front of a linked list. push() allocates memory for a node on the heap, but I cannot free the memory here because then the work done by push() will not be reflected in the caller (main()). So how can I free the concerned heap-allocated memory from inside main()?
Any sort of help is appreciated. Thanks in advance.
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *next;
};
/* Prototypes */
void push(struct node **headRef, int data);
int main(void)
{
struct node *head, *tail, *current;
int i;
head = NULL;
// Deal with the head node here, and set the tail pointer
push(&head, 1);
tail = head; // tail and head now point to the same thing
// Do all the other nodes using TAIL
for (i = 2; i < 6; i++)
{
push(&(tail->next), i); // add node at tail->next
tail = tail->next; // advance tail to point to last node
}
current = head;
while (current)
{
printf("%d ", current->data);
current = current->next;
}
printf("\n");
return 0;
}
/*
Takes a list and a data value.
Creates a new link with the given data and pushes
it onto the front of the list.
The list is not passed in by its head pointer.
Instead the list is passed in as a "reference" pointer
to the head pointer -- this allows us
to modify the caller's memory.
*/
void push(struct node **headRef, int data)
{
struct node *newNode = malloc(sizeof(struct node));
newNode->data = data;
newNode->next = *headRef; // The '*' to dereference back to the real head
*headRef = newNode; // ditto
}
You can free the allocated space in main like this -
struct node * tmp;
while(head){
tmp = head;
head = head->next; //this is to avoid loosing reference to next memory location
free(tmp);
}
Since you pass address of variable in push, therefore, this could be possible.
typedef struct LIST{
int count = 0;
}LIST;
typedef struct NODE{
int data;
struct NODE *link;
}NODE;
int main() {
NODE *p1, *p2, *p3;
p1 = (NODE*)malloc(sizeof(NODE));
p1->link = NULL;
p2 = (NODE*)malloc(sizeof(NODE));
p2->data = 20;
p2->link = NULL;
p1->link = p2;
I want to make add NODE function and list to control NODE.
Give me some answer to solve this problem.
you should define head in the list.
node * head;
Insert function as follows, to insert value in ascending order.
void insert(int val)
{
node * nd = new node();
nd->val = val;
if(head == NULL)
head = nd;
else
{
if(val <= head->val)
{
nd->next = head;
head = nd;
}
else
{
node * itr = head;
while(itr->next != NULL && itr->next->val <= val)
itr = itr->next;
nd->next = itr->next;
itr->next = nd;
}
}
}
First you probably want to add to your LIST struct a field "NODE *first", which points to NULL initially, and then will point to the first element of your list.
Then what does you add function should do? Add to the beginning or the end of the list?
If at the beginning: allocate a NODE, set its link pointer to the first element of your list and say that the first element of the list is now the node that you just allocated.
Try to give variable according to their work, so that it is easy to understand.
struct node
{
int val;
struct node* next;
};
void insert(struct node** head_ref, int data)
{
struct node* new_node = (struct node*)malloc(sizeof(struct node));
new_node->val = data;
new_node->next = (*head_ref);
(*head_ref) = new_node;
}
int main()
{
struct node* head = NULL;
insert(&head,1);
insert(&head,2);
return 0;
}
Note that : Insert function will always add the value at front.
Try to write function for particular task.
I'll avoid giving you the entire answer in C code since it's in general better to "teach a man to fish".
I would suggest that you add a NODE * member to your LIST class to store the header node of your linked list.
The addNode that adds a node to the next node should look like this:
void addNode (LIST* list, NODE * penultNode, int newData);
// list: Address to the linked list info object
// penultNode: Address to the node after which you want to add a new node.
// Should be NULL if your linkedlist is empty
// newData: Data in the new node that you wanna add
Inside this function, your actions will depend on whether penultNode is NULL or not. If it is not null, your job is simple. You just allocate a new NODE object and set the pointer of penultNode->next to the new object. If it is NULL, that means that no node exists in the list yet. In this case, you will need to set the pointer of list->headerNode to the new NODE object.
http://cslibrary.stanford.edu/103/
Please find some time to go through the wrong push function in this linked list basics document. I just followed the same implementation of this function. So according to the document the addition of data to the head of the list shouldn't happen. But mine works perfectly fine with the way they said it has to be implemented. I am very confused about finding out what the problem is?
Here is the code:
#include<stdio.h>
#include<stdlib.h>
struct node{
int data;
struct node * next;
};
typedef struct node Node; /* Utilize a typedef for Node rather than typing
struct Node everytime we declare a node. */
Node* BuildOneTwoThree() {
Node* head =NULL; // pointer called head.
Node* second =NULL; // pointer to second memory block
Node* third = NULL; // pointer to third memory block
head = (Node*)malloc(sizeof(Node)); //allocate a memory block of size node
//in the heap and head pointer will
//point to this memory.
second = (Node*)malloc(sizeof(Node)); //allocate a memory block of size node
//in the heap and second pointer will
//point to this memory
third = (Node*)malloc(sizeof (Node)); //allocate a memory block of size node
//in the heap and third pointer will
//point to this memory
head->data = 1;
head->next = second; //the next pointer of node type will point to another
//pointer of node type which is second!!
second -> data = 2;
second -> next = third;
third -> data = 3;
third -> next = NULL;
return head;
}
Node* WrongPush(Node* head, int data) {
Node* newNode = malloc(sizeof(Node));
newNode->data = data;
newNode->next = head;
head = newNode; // NO this line does not work!
return head;
}
Node* WrongPushTest() {
Node* head = BuildOneTwoThree();
Node* current = WrongPush(head, 4);
return current;
}
int main(){
Node* ptr = WrongPushTest(); //My question is why does the wrong push
//test implementation that I setup work?
while(ptr!=NULL) {
printf("%d\n",ptr->data);
ptr=ptr->next;
}
}
The first thing I notice is that you actually changed the implementation as written in the document you referenced. The document implements WrongPush as follows (which I modified to use your structure definition):
void WrongPush (Node * head, int data) {
Node * newNode = malloc(sizeof(Node));
newNode->data = data;
newNode->next = head;
head = newNode; /* This will not work because you are not
modifying head in the calling function. */
}
The problem with your implementation is that it is not easily scalable. For example, using your code, try WrongPushTest as follows:
Node * WrongPushTest() {
Node * head = BuildOneTwoThree();
Node * current = WrongPush(head, 4);
current = WrongPush(head, 5);
current = WrongPush(head, 6);
}
The output will not be something that the programmer had intended. The goal is to have a push function that utilizes the original head without having to create a new node everytime you push another node onto the linked list. The example they use in the document is as follows:
void Push(Node** headRef, int data) {
Node * newNode = malloc(sizeof(Node));
newNode->data = data;
newNode->next = *headRef;
*headRef = newNode;
}
Notice that I am not returning a pointer to the newly created head as was done in your example. The above allows us to always push a new node onto the head of the original linked list by directly manipulating the original head pointer.
Node * PushTest() {
Node * head = BuildOneTwoThree();
Push (&head, 4);
Push (&head, 5);
Push (&head, 6);
return head;
}
Hopefully this helps to clear things up for you!
I'm following the Stanford CS Ed Library tutorial on Linked Lists. I am trying to add a new list to the front of my linked list, and it's not working based on the printout I get from the Length function defined below.
#include <stdio.h>
#include <stdlib.h>
//build new struct for node
//node has value and points to next node
struct node{
int value;
struct node *next;
};
//declare a new struct node that contains 3 nodes (head, middle, tail)
struct node *Build123(){
struct node *head, *middle, *tail = NULL;
head = malloc(sizeof(struct node));
middle = malloc(sizeof(struct node));
tail = malloc(sizeof(struct node));
head->value = 3;
head->next = middle;
middle->value = 5;
middle->next = tail;
tail->value = 9;
tail->next = NULL;
return head;
};
//declare a function Length and variable counter to calculate size of list
int Length(struct node *head) {
int count = 0;
struct node *iterator = head;
while (iterator != NULL) {
count++;
iterator = iterator->next;
}
return count;
}
//declare function Push to add new lists that would be added to the front
void Push (struct node **headRef, int value){
struct node *newNode;
newNode = malloc(sizeof(struct node));
newNode->value = value;
newNode->next = *headRef;
}
int main(){
//instantiate the 3 element linked list named beast
struct node *beast = Build123();
//add 2 elements to the front of the linked list via pass by reference
Push(&beast, 6);
Push(&beast, 12);
//calculate length of linked list after elements have been added
int len = Length(beast);
//print length of linked list to screen
printf("%d\n",len);
return 0;
}
I get 3, when I expect to receive 5. Would you please assist me to find the error in the code that prevents me from obtaining the value I expect? I could not figure out why despite much tinkering. Thank you!
The problem is that when you do something like Push(&beast, 6); what beast points to is unchanged by the function Push. Even though Push adds more elements to the linked list, when you call Length on beast later it calls it on the same node that beast originally had at the start - so it is completely unknowing of the extra, added nodes.
At the end of Push(), you need to do this:
*headRef = newNode;
so that beast will correctly point to the new start of the list.
You don't modify headRef in your Push function, so your list's head never actually changes. beast always stays pointing to the original node it was created to point to. Add this line:
*headRef = newNode;
In Push(), and you'll be set.
At the end of the push() method, you have to add:
*headRef = newNode
This is because headRef should always point to the first node in your linked list.