Basically what title says, Im trying to append (add to end of my list). my BuildList function takes in a size parameter that determines how many nodes the list will have. my problem is with my append function. So if I have 5 as my head, how do I fix my append function so that random numbers will be added after 5?
typedef struct Node
{
int value;
struct Node* next;
} Node;
Node *createNode( int num )
{
Node *ptr;
ptr = (Node *) malloc( sizeof( Node ) );
ptr->value = num;
ptr->next = NULL;
return ptr;
}
Node* append (Node* head, Node* newNode)
{
if (head == NULL)
return newNode;
while (head -> next != NULL);
head -> next = newNode;
return head;
}
Node* buildList (int size)
{
Node* newNode = (Node*) malloc (sizeof(Node));
Node* head = NULL;
for (int i = 0; i < size; i++)
{
Node* newNode = createNode (rand () % 10);
head = append (head, newNode);
}
return head;
}
Well, the most glaring issue is this
while (head -> next != NULL);
I believe you meant to write something like this
Node *tmp = head;
while (tmp -> next != NULL) {
tmp = tmp->next;
}
tmp->next = newNode;
You don't want to modify head here since you return it later in the function. If you didn't use tmp, head would always point to the penultimate node in the list.
You just need to modify your while, why do you have an empty instruction there? If the head is not NULL then you will never exit:
while (head -> next != NULL)
{
head = head -> next;
}
Related
When I run the program it works except when I delete a fairly large number such as 100 or above, whenever I input anything remotely as large as that number I get the Heap use after free error. The terminal is saying it is caused by line 53 in insert() which is this line, tail->next = newNode;. I know keeping head and tail pointers as global variables are not the best way to write it, but I will change it once I get this to work.
void insert(int nData) {
struct Node *newNode = (struct Node*)malloc(sizeof(struct Node)+10);
newNode->data = nData;
newNode->next = NULL;
if(checkDuplicates(nData)==1){
return;
}else{
if(head == NULL){
head = newNode;
tail = newNode;
}
else {
tail->next = newNode;
tail = newNode;
}
}
}
void delete(int n){
if(head -> data==n){
struct Node *tempHead = head;
head= head -> next;
free(tempHead);
return;
} else{
struct Node *current = head;
struct Node *prev = NULL;
while(current!=NULL&¤t->data!=n){
prev = current;
current = current -> next;
}
if(current==NULL) return;
prev->next = current->next;
free(current);
}
}
There is a possible case where tail->next = newNode would be executed on a freed node: that happens when earlier on you called delete and that deleted the tail node in the list. In that case your code does not adjust the value of tail.
So in delete change:
head = head -> next;
to:
head = head -> next;
if (head == NULL) {
tail == NULL;
}
And in the else block change:
prev->next = current->next;
free(current);
to:
prev->next = current->next;
if (tail == current) {
tail = prev;
}
free(current);
For starters the function insert can produce a memory leak because at first a memory is allocated
struct Node *newNode = (struct Node*)malloc(sizeof(struct Node)+10);
(moreover it is unclear what the magic number 10 means in this expression sizeof(struct Node)+10). And then if the condition of the if statement
if(checkDuplicates(nData)==1){
return;
evaluates to logical true the function exits without freeing the allocated memory.
You need at first to check whether the value is not already present in the list and only after that to allocate memory for the new node.
As for the reason of the error then it seems the reason of the error is inside the function delete. The function does not reset the pointer tail when a single node is present in the list or when the node pointed to by the pointer tail is removed.
And apart from this even the first statement of the function
if(head -> data==n){
can invoke undefined behavior when the function is called for an empty list.
The function should be defined the following way
int delete( int n )
{
struct Node *current = head;
struct Node *prev = NULL;
while ( current != NULL && current->data != n )
{
prev = current;
current = current->next;
}
int success = current != NULL;
if ( success )
{
if ( prev == NULL )
{
head = head->next;
if ( head == NULL ) tail = NULL;
}
else
{
prev->next = current->next;
if ( prev->next == NULL ) tail = prev;
}
free( current );
}
return success;
}
I created a program in c which :
Creates a simple linked list in c in which I store letters
Print the content of every node
delete the last node
Print the content of the list again
The problem is with the "delete_last" function because prints in terminal an infinite loop (I believe that the problem is invoked when I use free funtion.)
#include<stdio.h>
#include<stdlib.h>
typedef struct node {
char xar;
struct node *next;
}Node;
void insert_list(Node **head , int len)
{
char x;
Node **list;
Node *node1 , *node2;
node1=(Node*)malloc(sizeof(Node));
printf("Give 5 characters : ");
x=getchar();
node1->xar = x;
node1->next=NULL;
list=&node1;
int i=0;
for(i=1 ; i < len ; i++)
{ x=getchar();
node2 = (node*)malloc(sizeof(node));
node2->xar = x;
node2->next = NULL;
(*list) -> next = node2;
list = &(*list) -> next ;
}
*head=node1;
}
void print_list(Node *head)
{
Node**lpp;
for(lpp=&head ; *lpp!=NULL ; lpp=&(*lpp)->next)
{
printf("\n the chars are %c" , (*lpp)->xar);
}
}
void delete_last(Node *head)
{
Node **lpp;
lpp=&head;
while((*lpp)->next!=NULL)
{
lpp=&(*lpp)->next;
}
free(*lpp);
}
int main()
{
Node *kefali ;
kefali = NULL;
insert_list(&kefali , 5);
print_list(kefali);
printf("\n");
delete_last(kefali);
print_list(kefali);
return 0;
}
You mustn't access to freed objects.
In the delete_last functon, you called free() for one of the nodes, but you didn't update any pointers there. This will have the following call of print_list access a freed object, invoking undefined behavior.
You should add
*lpp = NULL;
after
free(*lpp);
To get the freed node out of the list.
Note that this won't work for removing the first (only) element in the list because the head is passed as a copy. You should change the function to accept a pointer to the head pointer to enable it remove the first element.
Your delete_last lacks a way of telling that the last element was deleted. Either pass a pointer to head or return a new head.
Further, it's way to complicated. Using lpp as pointer to pointer is not necessary - it only complicates the code. Keep it simple.
Here is an example which returns the new head.
Node* delete_last(Node *head)
{
if (head == NULL) return NULL; // empty list
if (head->next == NULL)
{
// Only one element...
free(head);
return NULL;
}
Node *prev = head;
Node *lpp = prev->next;
while (lpp->next)
{
prev = lpp;
lpp = prev->next;
}
prev->next = NULL;
free(lpp);
return head;
}
and call it like:
head = delete_last(head);
Here is an example which takes a pointer to head.
Node* delete_last(Node **head)
{
if (head == NULL) exit(1); // illegal call
if (*head == NULL) return NULL; // empty list
if ((*head)->next == NULL)
{
// Only one element...
free(*head);
*head = NULL;
return;
}
Node *prev = *head;
Node *lpp = prev->next;
while (lpp->next)
{
prev = lpp;
lpp = prev->next;
}
prev->next = NULL;
free(lpp);
}
and call it like:
delete_last(&head);
You do not update the previous node (you need to keep track on it when iterating)
This makes no sense as you take reference to the local variable head and it does not change the the head of list when last element is deleted.
Node **lpp;
lpp=&head;
To prevent double-pointer function returns the head. Assign it when called. If return value is NULL the last element was deleted
Node *delete_last(Node *head)
{
Node *lpp = NULL, *prev;
if(head)
{
lpp=head -> next;
prev = head;
while(lpp->next)
{
prev = lpp;
lpp = lpp -> next;
}
if(prev == head && lpp == NULL)
{
free(head);
head = NULL; //empty list
}
else
{
free(lpp);
prev -> next = NULL;
}
}
free(lpp);
return head;
}
You can also use double pointer to modify the head when needed:
void delete_last(Node **head)
{
Node *lpp = NULL;
if(head && *head)
{
if(!(*head) -> next)
{
free(*head);
*head = NULL;
}
else
{
lpp = *head;
while(lpp -> next -> next)
{
lpp = lpp -> next;
}
free(lpp -> next);
lpp -> next = NULL;
}
}
}
I have the following node structure in C:
#define SIZE 5
typedef struct node
{
int n;
struct node* next;
}node;
node* head = NULL;
void implement(int n); // create linked list
int length(void); // returns length of list
node* reverse(void); // reverses order of list
The list is implemented as follows:
void implement (int n)
{
for (int i = 0; i < n; i++)
{
node* new_node = malloc(sizeof(node));
if(new_node == NULL)
{
printf("out of memory!\n");
return;
}
new_node->n = i;
new_node->next = head;
head = new_node;
}
}
Which when printed to the terminal gives:
4 3 2 1 0
The head pointer is set to node 4.
I have written the following function to reverse the list as follows:
node* reverse(void)
{
node* cur = head;
node* next = NULL;
head = NULL;
while (cur->next != NULL)
{
next = cur->next;
cur->next = head;
head = cur;
cur = next;
}
return cur;
}
However, returning cur only gives:
0
Returning head provides:
1 2 3 4
So it is quite clear that the list is being reversed, but for some reason the last node (0) is not being linked to the remaining nodes. I am probably missing something obvious here, but can anyone give me any pointers? (no pun intended!)
Cheers
while (cur->next != NULL)
This stops when cur is at the last element (next is NULL); i.e. you don't process the last node.
Changing it to
while (cur != NULL)
and returning head should fix it.
#include<stdio.h>
#include<stdlib.h>
typedef struct Node{
int val;
struct Node* next;
} Node;
void add_at_end(Node* head, int val){
Node* newNode = malloc(sizeof(Node));
newNode -> next = NULL;
Node* temp = head;
if(head -> next == NULL){
head ->val = val;
head -> next = newNode;
}
else{
while(temp -> next != NULL){
temp = temp -> next;
}
temp -> next = newNode;
temp -> val = val;
}
}
void display(Node* l){
while(l->next != NULL){
printf("%d -->", l->val);
l = l->next;
}
printf("End\n");
}
As I said in the question, I'm creating a useless node at the end just to specify NULL. How can I remove that feature? I know I'm doing something wrong in the add_at_end function but I'm not able to rectify it. Help would be appreciated. Thanks
EDIT:
#include<stdio.h>
#include<stdlib.h>
typedef struct Node{
int val;
struct Node* next;
} Node;
typedef struct List{
Node* head;
} List;
void add_at_end(List* l, int val){
Node* newNode = malloc(sizeof(Node));
newNode -> next = NULL;
newNode -> val = val;
Node* temp = l->head;
if(temp == NULL){
l->head = newNode;
}
else{
while(temp->next != NULL){
temp = temp -> next;
}
temp -> next = newNode;
}
}
void display(List* l){
Node* t = l -> head;
while(1){
printf("%d\n", t->val);
if(t->next == NULL) break;
t = t->next;
}
}
int main(){
List l;
l.head = NULL;
add_at_end(&l, 10);
add_at_end(&l, 20);
add_at_end(&l, 30);
display(&l);
return 0;
}
This is my final code.
I need help adding nodes to the middle of the list. How can I do that?
Your node usage is all confused. When you create a new node the value should be stored into that node and the node linked into the list. Instead what you are doing is trying to add the value into the last node and then linking in a dummy node. It's a bit convoluted so I'm not sure I've explained what you have done clearly. Here is what add_to_end should be more like:
add_to_end (Node** head, int val)
{
Node* temp;
Node* newNode = malloc(sizeof(Node));
if (!newNode) {
/* Error */
}
newNode->val = val;
newNode->next = NULL;
if (!*head) {
/* empty list. Just make new node the head */
*head = newNode;
} else {
/* Find the end of the list */
temp = *head;
while (temp->next) {
temp = temp->next;
}
/* temp is now the last node. Chain new node after it */
temp->next = newNode;
}
}
Instead of a null node, you can represent the end of the list with a value of NULL, i.e. with a null pointer. The list is empty when head is NULL and the last node has node->next == NULL.
For this to work, you must be able to update the head when you add a node, because after inserting the frst node, the head will no longer be NULL. (The same goes for inserting at the front or deleting the first node.)
This chan be achieved by passing a pointer to a node pointer:
void add_at_end(Node **head, int val)
{
Node* newNode = malloc(sizeof *newNode);
newNode->next = NULL;
newNode->val = val;
while (*head) {
head = &(*head)->next;
}
*head = newNode;
}
Then you call add_at_and like this:
Node *head = NULL;
add_at_end(&head, 1);
add_at_end(&head, 2);
add_at_end(&head, 3);
It is important that head is initialised to NULL. More generally, all your pointers should either be NULL or point to valid nodes.
#include<stdio.h>
#include<stdlib.h>
typedef struct Node{
int val;
struct Node* next;
} Node;
void add_at_end(Node* head, int val){
Node* newNode = (Node *)malloc(sizeof(Node));
newNode -> next = NULL;
if(head == NULL)
{
head = new_node;
head->val = val;
}
if(head -> next == NULL)
{
new_node ->val = val;
head -> next = newNode;
}
else{
Node *temp = head;
while(temp -> next != NULL){
temp = temp -> next;
}
temp -> next = newNode;
temp -> val = val;
}
}
void display(Node* l){
while(l->next != NULL){
printf("%d -->", l->val);
l = l->next;
}
printf("End\n");
}
#include<stdio.h>
#include<stdlib.h>
struct node {
int num;
struct node *next;
}*head=NULL, *curr=NULL;
void print(){
curr = head;
while(curr != NULL){
printf("%d\n", curr->num);
curr = curr->next;
}
}
struct node* memAlo(){
return (struct node *)malloc(sizeof(struct node));
}
void addNode(int no){
curr = head;
while(curr != NULL){
curr = curr->next;
}
curr = memAlo();
if(curr == NULL){
printf("\nmemory up\n");
return;
}
else{
curr->num = no;
curr->next = NULL;
printf("%d\n",curr->num);
}
}
void hellop(){
printf("%d", head->num);
}
int main(){
int i;
curr = head;
for(i=1;i<10;i++){
addNode(i);
}
print();
/*head = memAlo();
head->num = 1;
head->next = NULL;
hellop();*/
}
I am sure I have messed up somewhere. The thing is that the head pointer doesn't get the memory allocated by the memAlo() fn() but how to get there? Please help
What I am trying is to create a singly linked list holding numbers from 1 to 9 and to print them using print(). Actually AddNode() is to create single node at the end of the linked list each time the for loop in main() executes.
You set head = NULL at the point where you first defined head. Except in that one place, we never see head on the left-hand side of = anywhere in your program. So of course head is always equal to NULL and never anything else.
You will probably want to insert some code at the start of your addNode function to test whether head == NULL at that point; and if that is true, you will want to assign the result of memAlo() to head instead of curr. You will have to adjust some of the other logic as well.
Your code for allocating a node is wrong. It should create a node, make some space for it, then return it.
struct node *memAlo() {
struct node *nd = malloc(sizeof(*nd));
return nd;
}
This creates a pointer to a node, properly allocates it, then returns it.
Problems I see:
Not dealing with empty list, i.e. when head == NULL.
Creating nodes that are not linked to each other.
curr = memAlo();
allocated memory for a node and returns it to you, but it does not connect the node with anything else.
Try this:
void addNode(int no){
struct node* temp = NULL;
// Deal with an empty list.
if ( head == NULL )
{
head = memAlo();
head->num = no;
head->next = NULL;
}
// Move curr until we reach the last node of the list.
curr = head;
while(curr->next != NULL){
curr = curr->next;
}
temp = memAlo();
if(temp == NULL){
printf("\nmemory up\n");
return;
}
else{
// Link the new node to the previous last node.
temp->num = no;
temp->next = NULL;
printf("%d\n",temp->num);
curr->next = temp;
}
}
It seems that since head is initially NULL, and then you start allocating nodes without saving the address of the first one, you lose the address of the first one, and then can't walk the list from the beginning.
The part you commented out illustrate the problem.
As a side note, there is no free in your program. Remember to always free the memory you alloc
#include<stdio.h>
#include<stdlib.h>
struct node
{
int num;
struct node *next;
};
struct node *head, *curr;
struct node *pos;
void addNode(int n)
{
if(head==NULL)
{
head = (struct node*)malloc(sizeof(struct node));
head->num = n;
head->next = NULL;
curr = head;
}
else
{
while(curr != NULL)
{
pos = curr;
curr = curr->next;
}
curr = (struct node*)malloc(sizeof(struct node));
curr->num = n;
curr->next = NULL;
pos->next = curr;
}
}
void printList()
{
curr = head;
while(curr != NULL)
{
printf("%d",curr->num);
curr = curr->next;
}
}
int main()
{
head = NULL;
curr = head;
int i, a[] = {4,5,1,2,3,9,0};
for(i=0;i<7;i++)
{
addNode(a[i]);
}
curr = head;
printList();
}
This seems to have solved my problem. I figured it out though. Thanks for all your help.