I have an algorithm that should create a singly linked list from a textbook. It barely touched on any examples, so I would need some help figuring it out (still new to C.)
Essentially, the algorithm runs as follows:
Algorithm: CREATE (HEAD, ITEM)
1. [Create NEW node]
a) Allocate memory for NEW node.
b) IF NEW = NULL then Print: “Memory not Available” and Return
c) Set NEW→DATA = ITEM
d) Set NEW→LINK = NULL
2. [Whether List is empty, head is the content of HEADER]
If HEAD = NULL then Set HEAD = NEW
3. Else
a) Set Temp = HEAD
b) While Temp→LINK ≠ NULL do
Set Temp = Temp→LINK
[End of while]
c) Set Temp→LINK = NEW
[End of IF]
4. Return
Here is what I have tried so far, but I could not understand the arrow mappings in the algorithm. Are these existing C features?
#include <stdlib.h>
#include <stdio.h>
typedef struct node {
int DATA;
struct node * LINK;
} node_t;
node_t *create(int head, int item){
node_t* new = NULL;
new = (node_t *)malloc(5*sizeof(node_t));
if(new == NULL){
prtinf("Memory not available");
return -1;
}
}
The arrow operator (->) in the algorithm is used to access a member of a struct using a pointer to that struct. It is equivalent to using the dot operator (.) to access a member of a struct, but with the added step of dereferencing the pointer to the struct. For example, if p is a pointer to a struct node, then p->DATA is equivalent to (*p).DATA.
In your code, you are using the node_t typedef to define the struct node type. This means that you can use node_t * to refer to a pointer to a struct node, and you can use node_t->DATA to access the DATA member of a struct node pointed to by node_t.
It looks like you are trying to implement the first step of the algorithm, which is to allocate memory for the new node and store the ITEM value in the DATA member of the node. You are using malloc to allocate memory for the new node, but you need to initialize the DATA member and the LINK member of the node. You can do this by using the arrow operator to access the members of the node:
node_t *create(int head, int item){
node_t* new = NULL;
new = (node_t *)malloc(sizeof(node_t));
if(new == NULL){
printf("Memory not available");
return -1;
}
new->DATA = item; // Set the DATA member of the new node
new->LINK = NULL; // Set the LINK member of the new node to NULL
}
You also need to return the new node from the create function so that you can use it later in the algorithm.
node_t *create(int head, int item){
node_t* new = NULL;
new = (node_t *)malloc(sizeof(node_t));
if(new == NULL){
printf("Memory not available");
return -1;
}
new->DATA = item; // Set the DATA member of the new node
new->LINK = NULL; // Set the LINK member of the new node to NULL
return new; // Return the new node
}
You can then use the create function to create a new node and store it in a local variable in your main program. This will allow you to continue implementing the rest of the algorithm.
int main() {
int head = 0; // The head of the linked list
int item = 5; // The data to store in the new node
node_t *new_node = create(head, item); // Create a new node
// Continue implementing the rest of the algorithm...
return 0;
}
Related
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.
When i want to add item to linked list my program crashes.
This are my structs that i'm using
typedef struct seats
{
int number, reserved;
char name[1000];
} seats;
// node list
typedef struct node
{
seats seat;
struct node * next;
} node_t;
And this is my insert function
void AddSeat(node_t * head, seats a_seat) // unos podataka na kraj liste
{
node_t * current = head;
while (current->next != NULL) {
current = current->next;
}
/* now we can add a new variable */
current->next = malloc(sizeof(node_t));
current->next->seat = a_seat;
current->next->next = NULL;
}
Actually I think your logic is wrong.
In a linked list you start with an empty node:
[ ]->
When you have something to store you fill the node.
[X]->
Then you create a new empty node at the end of it.
[X]->[ ]
And so forth.. And so on..
[X]->[X]->
[X]->[X]->[ ]
In your code, you are adding the value to the new element. When you are at the end of the list you assign the seat to the current node and then create a new (empty) node at the end. You should also create a variable for the node, allocate memory for it and then point the node to it.
For the linked list to work, where you have
/* now we can add a new variable */
current->next = malloc(sizeof(node_t));
current->next->seat = a_seat;
current->next->next = NULL;
you should have
void AddSeat(node_t *head, seats a_seat){
node_t *current = head;
node_t *new_node;
...
new_node = malloc(sizeof(node_t));
current->seat = a_seat;
current->next = new_node;
...
}
Also please consider following some good practices when writing code in C like ataching the pointer operator (*) to the variable name (char *var instead of char * var) and properly indent your code. It improves readability a lot.
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.
I am newbie in C and I am trying to write a linked list in which each node simply contains an int. The definition of the structure is ok, but I also want to write methods to update this linked list (add element at the tail and delete the head element). (I want to be able to read the most recently added element)
I wrote the functions below, but I don't know where the free should take place and how to implement it. Could anyone help me with this?
typedef struct Node{
Node next = NULL;
int number;
} Node;
void add_node(Node *LL,int val){
// add node to the end of the linked list
new_node = (struct Node *)malloc(1*sizeof(struct Node));
new_node->number = val;
Node n = *LL;
while (n.next != NULL){
n = n.next;
}
n.next = new_node;
}
void delete_head(Node *LL){
// update the head
*LL = LL->next;
//free?
}
void update_LL(*LL,int val){
add_node(*LL,val);
delete_head(*LL);
}
I rename your data structure this way:
struct pointer
{
int field;
struct pointer *link;
};
typedef struct pointer cell;
Then we can use this function for your need:
void ad_an_element_at_the_end_of_the_list()
{
cell *p=NULL;
cell *ptr=head;
int value;
cout<<" Integer number to insert at the end of the list: ";
cin>>value;
p=(cell*)malloc(sizeof(cell));
p->field=value;
p->link=NULL;
if(ptr==NULL)
{
ptr=p;
head=ptr;
}else
{
if(ptr->link==NULL) t
{
ptr->link=p;
head=ptr;
}else
{
while(ptr->link!=NULL)
{
ptr=ptr->link;
}
ptr->link=p;
}
}
}
Try changing *LL = LL->next; for Node *nextNode = LL->next;.
Then you can call free(LL) followed by LL = nextNode.
void delete_head(Node *LL){
Node *nextNode = LL->next;
free(LL);
LL = nextNode;
}
This then frees the Node at the head and moves the pointer to the next one in the Linked List.
You need to save your link to node which is next before you delete current node. Otherwise you won't be able to refer any node of your linkedlist. Now when you have backed up your link to next node, you can free current node pointed by LL, and then assign LL pointer to next node which you had earlier backed up in temp pointer.
Node *temp = LL->next;
free(LL);
LL = temp;
Possibly a duplicate of this question LinkedList - How to free the memory allocated using malloc
Basically you have to store the pointer to the node you want to delete otherwise you will leak that memory as there will be no reference to that memory location anywhere in your code.
try this in your delete_head function:
Node *temp = LL;
*LL = LL->next;
free(LL);
Hope this helps!
I have created a List data structure implementation for generic data type with each node declared as following.
struct Node
{
void *data;
....
....
}
So each node in my list will have pointer to the actual data(generic could be anything) item that should be stored in the list.
I have following signature for adding a node to the list
AddNode(struct List *list, void* eledata);
the problem is when i want to remove a node i want to free even the data block pointed by *data pointer inside the node structure that is going to be freed. at first freeing of datablock seems to be straight forward
free(data) // forget about the syntax.....
But if data is pointing to a block created by malloc then the above call is fine....and we can free that block using free function
int *x = (int*) malloc(sizeof(int));
*x = 10;
AddNode(list,(void*)x); // x can be freed as it was created using malloc
what if a node is created as following
int x = 10;
AddNode(list,(void*)&x); // x cannot be freed as it was not created using malloc
Here we cannot call free on variable x!!!!
How do i know or implement the functionality for both dynamically allocated variables and static ones....that are passed to my list....
Thanks in advance...
The complete implementation is as following list.h simply contains function prototypes.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include "list.h"
//structure of each node
static struct Node{
void *Data;
struct Node * Next;
struct Node * Prev;
};
//complete list interface
struct List{
int Size;
struct Node DummyNode; //dummy node
void (*Print)(void *Data);
};
//create new List
struct List * CreateList(void(*Print)(void* Data)){
struct List *newList = (struct List *)malloc(sizeof(struct List));
if(newList != NULL){
newList->DummyNode.Data = NULL;
newList->DummyNode.Next = newList->DummyNode.Prev = &newList->DummyNode;
newList->Size = 0;
newList->Print = NULL;
if(Print != NULL) newList->Print = Print; // hook to user provided print function
return newList;
}
return NULL;
}
//Node *ptr point to one node before the actual node to be removed
static void _RemoveNode(struct List *list, struct Node *ptr)
{
struct Node *temp = ptr->Next; //catch hold of node that is to be removed
ptr->Next = temp->Next; // link previous node's next pointer with the temp node next pointer
temp->Next->Prev = ptr; // link next node's previous pointer with previous node pointer
temp->Prev = NULL; // unlink from previous node
temp->Next = NULL; // unlink from next node
free(temp->Data); // free the data ............ !!! need to mode generic before cleaning the resource
free(temp); // remove the node itself.
list->Size--;
}
void RemoveNodeAt(struct List *list,int nodeIndex)
{
if( list->Size > 0 && (nodeIndex >= 0 && nodeIndex < list->Size)){
int i=-1; // meaning we are at dummy node
struct Node *ptr = NULL;
for(ptr = &list->DummyNode ;i < nodeIndex - 1 ;i++) // traverse up to one node before the actual node
ptr = ptr->Next;
_RemoveNode(list,ptr);
}
}
//Node *ptr point to one node before the actual node to be removed
static void _AddNode(struct List *list, struct Node *ptr,void *data)
{
//create New Node
struct Node *newNode = (struct Node*)malloc(sizeof(struct Node));
if(newNode != NULL){
newNode->Data = data;
//shift node at index to right
newNode->Next = ptr->Next;
newNode->Prev = ptr;
ptr->Next = newNode;
newNode->Next->Prev = newNode;
list->Size++;
}
}
void AddNodeAt(struct List *list,int nodeIndex,void *data)
{
//A node can be added just before head and just after tail.
if( nodeIndex >= 0 && nodeIndex <= list->Size){
int i=-1; // meaning we are at dummy node
struct Node *ptr = NULL;
for(ptr = &list->DummyNode ;i < nodeIndex - 1 ;i++) // traverse up to one node before the actual node
ptr = ptr->Next;
_AddNode(list,ptr,data);
}
}
void RemoveNode(struct List *list)
{
if(list->Size > 0){ //check if the list is not empty
struct Node * temp = list->DummyNode.Prev; //catch hold of last node
temp->Prev->Next = temp->Next; //establish previous node's next pointer to temp node next pointer
temp->Next->Prev = temp->Prev; //establish next node's previous pointer to temp node previous pointer
temp->Next = NULL; // unlink temp node from next node
temp->Prev = NULL; // unlink temp node from previous node
free(temp->Data); // free the data ............ !!! need to mode generic before cleaning the resource
free(temp); // remove the node itself.
list->Size--;
}
}
void AddNode(struct List *list,void *data)
{
struct Node *ptr = list->DummyNode.Prev;
//create New Node
struct Node *newNode = (struct Node*)malloc(sizeof(struct Node));
if(newNode != NULL){
newNode->Data = data;
//shift node at index to right
newNode->Next = ptr->Next;
newNode->Prev = ptr;
ptr->Next = newNode;
newNode->Next->Prev = newNode;
list->Size++;
}
}
void DeleteAllNodes(struct List *list)
{
struct Node *ptr = &list->DummyNode;
while(list->Size > 0){
_RemoveNode(list,ptr);
ptr = ptr->Next;
}
}
void Display(struct List *list)
{
if(list->Print != NULL){ //If conusmer doesnot provide a print function just give up printing process.
int i=0;
struct Node *ptr = &list->DummyNode;
for(i = 0; i < list->Size; i++){
ptr = ptr->Next;
list->Print(ptr->Data); // let the consumer of the list data structure print the way he wants
}
}
}
// must be used before inserting automatic variables are passed in to the list
// because freeing a automatic variable with free function is a crime....!!!! *(~_~)*
// So i want you to create clones of the automatic variables and pass those variables.
// AddNode(list,Clone(&i,sizeof(i)));
void * Clone(void *data, int size)
{
void * clone = malloc(size);
memcpy(clone,data,size);
return clone;
}
Well, the typical rule of thumb is that the allocator of heap space shall always also be the one who frees it. Things always start to get messy when it is not well defined which program module 'owns' the allocation.
In your example a clean implementation of the list would never delete the data itself, or would create a copy of the data on insertion such that the data truly belongs to the list. For this, also the size of the data has to be passed.
A good compromise that avoids unnecessary copies may be that the list always frees the data itself but on insertion the user can choose that no copy occurs. For this, he could pass size values of 0 or -1 to indicate that no copy is needed, as the data is already on the heap and will not be managed (freed) by sombody else.
If you are using such snippet
int x = 10;
AddNode(list, (void *)&x);
inside another function, where x is declared auto variable on stack, the code may not behave as you would expect. The pointer is generated from stack address and it's not guaranteed to hold that value of x when the function returns. The pointer you saved in the list will now point to some other data on the stack frame.
For clean implementation of a generic list, you should use dynamically allocated memory or global data which is not stored on stack. Your code will work for global or static variables but not for automatic variables.
There is no automatic way to know whether a pointer can be freed or not. If the logic of your program does not make it obvious, you are going to need a helper variable:
struct Node
{
void *data;
int data_on_heap; // on heap, so should be freed
....
....
};
You'll need to modify your AddNode function to take that info:
int *x = (int*) malloc(sizeof(int));
*x = 10;
AddNode(list, x, 1); // x can be freed as it was created using malloc
int x2 = 10;
AddNode(list, &x2, 0);
And when you want to free it, you'll have to check:
if (n->data_on_heap)
free(n->data);
Modify the AddNode function to always make a copy of the data passed to it, and free the data when you want to delete the node.