I am trying to implement a singly linked list in C and have trouble to create the Head node.
my code looks like this:
#include <stdio.h>
#include <stdlib.h>
typedef struct NODE{
int value;
struct NODE* next;
}node;
int append(node* head, int val){
if(head == NULL){
printf("Head is NULL");
head = malloc(sizeof(node));
if(head == NULL){
return EXIT_FAILURE;
}
head->value = val;
head->next = NULL;
} else {
printf("Head is not NULL");
while(head->next != NULL){
head = head->next;
}
head = malloc(sizeof(node));
head->value = val;
head->next = NULL;
}
return EXIT_SUCCESS;
}
int main(){
node* head = NULL;
append(head, 10);
append(head, 5);
append(head, 7);
return EXIT_SUCCESS;
}
when adding nodes, memory for the head should be allocated and then filled with the arguments, if it does not already exist. I can't figure out, why the Head always stays NULL.
Can anybody explain this to me?
I appreciate any help.
Thanks in advance :)
head is always NULL, because you are not modifying it, you are modifying its copied value instead.
In main(), do this:
append(&head, 10); // Modify head itself and not its copied value
Change the function signature to this:
int append(node** head, int val)
inside the function append() replace head with *head everywhere
There is one more problem with your code. In append() , there is no need of the while loop, since you will be permanently shifting the head to the end. You should not do this because head should always point to "head" of the linked list.
#include <stdio.h>
#include <stdlib.h>
typedef struct NODE
{
int value;
struct NODE *next;
} node;
int
append (node **head, int val)
{
if (*head == NULL)
{
printf ("Head is NULL");
*head = malloc (sizeof (node));
if (*head == NULL)
{
return EXIT_FAILURE;
}
(*head)->value = val;
(*head)->next = NULL;
}
else
{
printf ("Head is not NULL");
node * temp = malloc (sizeof (node));
temp->value = val;
temp->next = *head;
*head = temp;
}
return EXIT_SUCCESS;
}
int
main ()
{
node *head = NULL;
append (&head, 10);
append (&head, 5);
append (&head, 7);
return EXIT_SUCCESS;
}
Output:
Head is NULLHead is not NULLHead is not NULL
Related
I have looked at my code several times but couldn't find the problem. please tell me what I need to replace to get my code working.
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
struct node
{
int data;
struct node *next;
};
struct node *head;
void insert(int x)
{
struct node *temp=(struct node *)malloc(sizeof(struct node));
temp->data = x;
temp->next = NULL;
if (head == NULL)
{
temp->next = head;
head = temp;
return;
}
struct node *temp1 = head;
while(temp1 != NULL)
{
temp1 = temp1->next;
}
temp1->next = temp;
}
void display()
{
struct node *temp = head;
if (head == NULL)
{
printf("list is empty");
return;
}
else{
while(temp!=NULL)
{
printf("%d ", temp->data);
temp = temp->next;
}
}
}
int main()
{
head = NULL;
insert(3);
insert(5);
insert(6);
display();
}
The problem is in this code:
struct node *temp1=head;
while(temp1!=NULL)
{
temp1=temp1->next;
}
temp1->next=temp;
... the while loop won't end until temp1 is NULL, so after the loop ends, it is guaranteed that temp1 is a NULL pointer ... and then you dereference that NULL pointer (via temp1->next), which causes a crash. Probably what you want to do instead is while(temp1->next != NULL) {...}
while(temp1!=NULL)
{
temp1=temp1->next;
}
temp1->next=temp;
The only way out of this loop is for temp1 to be NULL. Then the next line attempts to used temp1 as a pointer. This is likely causing your issue. You need to instead check if the next is NULL and break leaving temp1 as the last in the list not it's next.
Pro tip for linked lists like this, they are a lot easier to modify with double pointers. Example code:
void append(struct node **list, int a) {
// skip to the end of the list:
while (*list != NULL) {
list = &(*list)->next;
}
*list = malloc(sizeof(struct node));
(*list)->data = a;
(*list)->next = NULL;
}
void display(struct node *list) {
while (list) {
printf("%d\n", list->data);
list = list->next;
}
}
void remove(struct node **list, int index) {
while (*list) {
if (--index == 0) {
struct node *temp = *list;
*list = temp->next;
free(temp);
break;
}
}
}
int main() {
struct list *mylist;
append(&mylist, 3);
append(&mylist, 4);
append(&mylist, 5);
display(mylist); // prints 3 4 5
remove(&mylist, 1);
display(mylist); // prints 3 5
remove(&mylist, 0);
remove(&mylist, 0);
// mylist is NULL again, all memory free'd
}
Note that this code needs no special cases for "is the list empty?", which makes it less complex than yours.
Using the delete_SLL function I want to delete the head of this singly linked list(head = 4). Although I get the correct output, the var struct Node* "temp" holding the value of the head isn't NULL. What is it about the variable "temp" that the free function not like? Is the node temp not Malloc-ed when setting it equal to the list head?
Source:Deleting a Node
Code:
#include <stdio.h>
#include <stdlib.h>
struct Node{
int item;
struct Node* next;
};
struct List{
struct Node* head;
struct Node* tail;
};
int SLL_empty(struct List* lst){
return lst->head == NULL ;
}
//newLst work
struct List newLst(){
struct List lst;
lst.head = NULL;
lst.tail = NULL;
return lst;
}
//Inserts a node to the front of the list[WORKS]
void insert_SLL(struct List* lst, int x){
struct Node* nde = (struct Node*)malloc(sizeof(struct Node));
nde->next = lst->head;
nde->item = x;
if (SLL_empty(lst))
lst->tail=nde;
lst->head = nde;
}
//Deletes a given Node
void delete_SLL(struct List* lst, int x){
struct Node* temp = (struct Node*)malloc(sizeof(struct Node));;
temp = lst->head;
struct Node* prev = NULL;`enter code here`
//If the head has the key
if (temp != NULL && temp->item == x){
lst->head = temp->next;
temp->next = NULL;
free(temp);
}
// stops once the key is found
while(temp != NULL && temp->item != x){
prev = temp;
temp= temp->next;
}
//If not in list
if (temp == NULL) return;
//If middle
if (temp != NULL && temp->item == x){
prev->next = temp->next;
temp->next = NULL;
}
//if at the end
if (temp != NULL && temp->item == lst->tail->item){
lst->tail= prev;
prev->next = NULL;
}
free(temp);
}
int SLL_pop(struct List *list){
struct Node* nde = list->head;
int item = nde->item;
list->head = nde->next;
free(nde);
if (SLL_empty(list))
list->tail = NULL;
return item;
}
int main(int argc, const char * argv[]) {
int i;
struct List list = newLst();
for (i = 0; i < 5; ++i)
insert_SLL(&list, i);
// printf("The length of the linkedLst is: %d\n",SLL_length(&list));
delete_SLL(&list, 4);
while ( list.head != NULL )
printf("Node: %d\n", SLL_pop(&list));
return 0;
}
The main purpose of free() is to ask the OS take the allocated memory back to the system. You might not be able to "see" that but if you try to access any element at the "temp" afterward, you should get an error.
While the "temp" in the program is only a variable. C doesn't require to, and can't change the given pointer to NULL due to pass-by-value sense. It's the programmer's work to remember that this pointer is no longer valid.
Or you can set it to NULL manually each time you free a pointer.
I am trying to implement a doubly linked list in order to study for an exam and am running into some trouble when inserting items into the tail -- it prints out correctly when I only insert to the head in the list. However, when I insert to the tail in the list only the last tail item is printed out. Below is my full code:
/*
- Q2: Write a function that takes a LinkedList struct pointer and inserts at the head of the linked list.
- Q3. Write a function that takes a LinkedList struct pointer and frees all memory associated with it. (
For a solution, see fancy-linked-lists.c, attached above.)
- Q4 Review all the functions from today's code and give their big-oh runtimes.
- Q5: Implement functions for doubly linked lists:
- tail_insert(),
- head_insert(),
- tail_delete(),
- head_delete(),
- delete_Nth().
- Repeat these exercises with doubly linked lists in which you maintain a tail pointer.
- How does the tail pointer affect the runtimes of these functions?
- Are any of these functions more efficient for doubly linked lists with tail pointers than they are for singly linked lists with tail pointers?
*/
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int data;
struct node *next;
struct node *prev;
} node;
node *createNode(int data)
{
node *ptr = NULL;
ptr = malloc(sizeof(node));
if(ptr == NULL)
{
printf("space could not be allocated\n");
return NULL;
}
ptr->data = data;
ptr->next = NULL;
ptr->prev = NULL;
return ptr;
}
node *tailInsert(node *head, int data)
{
if(head->next == NULL)
{
node *temp;
temp = createNode(data);
temp->next = NULL;
temp->prev = head;
head->next = temp;
return head;
}
tailInsert(head->next, data);
}
node *frontInsert(node *head, int data)
{
node *newHead;
if(head == NULL)
{
return createNode(data);
}
newHead = createNode(data);
newHead->next = head;
newHead->prev = NULL;
return newHead;
}
node *destroy_linked_list(node *list)
{
/*if (list == NULL)
return NULL;
// Free the entire list within this struct.
destroy_list(list->head);
// Free the struct itself.
free(list);
return NULL;
*/
}
void printList(node *head)
{
if (head == NULL)
{
printf("Empty List\n");
return;
}
for(; head != NULL; head = head->next)
printf("%d ", head->data);
printf("\n");
}
int main(void)
{
node *head = NULL;
head = frontInsert(head, 1);
head = frontInsert(head, 2);
head = frontInsert(head, 3);
head = tailInsert(head, 4);
head = tailInsert(head, 5);
head = tailInsert(head, 6);
printList(head);
system("PAUSE");
return 0;
}
I appreciate the help!
You are returning the temp(last node) from tailInsert and assigning to head. Do not change the head pointer if you are inserting at tail.
void tailInsert(node *head, int data)
{
if(head->next == NULL)
{
node *temp;
temp = createNode(data);
temp->next = NULL;
temp->prev = head;
head->next = temp;
return ;
}
tailInsert(head->next, data);
}
In main do not assign anything to head if you are calling tailInsert function
say I have the following code for inserting a node at the end to a linkedlist:
int main() {
struct Node* head = NULL;
newNode(head, 1);
newNode(head, 2);
newNode(head, 3);
print(head);
return 0;
}
void newNode(struct Node* head, int val) {
struct Node* curr_p = head;
struct Node* new_p = malloc(sizeof(struct Node));
new_p->data = val;
new_p->next = NULL;
if (head == NULL) {
curr_p = new_p;
// printf("head %d \n", head->data);
}
else{
while (curr_p->next != NULL) {
curr_p = curr_p->next;
}
curr_p->next = new_p;
}
}
void print(struct Node* head) {
struct Node* curr_p = head;
while (curr_p != NULL) {
printf("%d\n", curr_p->data);
curr_p = curr_p->next;
}
}
It appears what causes the error is in the if statement block where head == NULL, the head node pointer seems to unable to point to new node. I always ended up with a segmentation fault. any reason for this?
I guess that your fault is that you are passing the head pointer in value not in reference so the code doesn't change it's value because it just copies the pointer
so your code should look like this
newNode(struct Node** head , int val ) {
struct Node* curr_p = *head;
/*
*/
if(curr_p == NULL ) {
*head = new_p;
}/*....*/
}
and in the main
newNode(&head,1)
and the finale code would be
#include <stdio.h>
#include <stdlib.h>
struct Node{
int data;
struct Node * next;
};
void newNode(struct Node** head, int val) {
struct Node* curr_p = *head;
struct Node* new_p =malloc(sizeof(struct Node));
new_p->data = val;
new_p->next = NULL;
if ( curr_p == NULL) {
*head = new_p;
// printf("head %d \n", head->data);
}
else{
while (curr_p->next != NULL) {
curr_p = curr_p->next;
}
curr_p->next = new_p;
}
}
void print(struct Node* head) {
struct Node* curr_p = head;
while (curr_p != NULL) {
printf("%d\n", curr_p->data);
curr_p = curr_p->next;
}
}
int main() {
struct Node* head = NULL;
newNode(&head, 1);
newNode(&head, 2);
newNode(&head, 3);
print(head);
return 0;
}
and actually you don't have to use curr_p in the print function because the head pointer in the print function it's just a copy of the head pointer of the main function so it wouldn't change it's value if you do something like head = head->next ; in the print function .
You have not specified that where you are getting segmentation fault but my strong guess is that you would be getting at - printf("head %d \n", head->data);. Why? Because with your present code head is NULL (that's what you are passing from your main method) and then you try to de-reference a NULL then you WILL segmentation fault.
You must only de-reference a valid pointer. If the pointer variable is holding NULL or some uninitialized/default value then de-referencing it will result in segmentation fault.
Below is the fixed IF block.
if (head == NULL) {
head = new_p;
printf("head %d \n", head->data);
}
#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.