My program keeps on crashing. I think there's a problem in my logic. Please help! Thanks!
struct node{
int data;
struct node *prev,*next;
} *head = NULL;
void insert(){
struct node* temp = (struct node*) malloc (sizeof (struct node*));
int value;
printf("Enter an element");
scanf("%d",&value);
temp -> data = value;
temp -> next = NULL;
temp -> prev = NULL;
if(value < head -> data || head == NULL){
temp -> next = head -> next;
head = temp;
return;
}
while(head->next != NULL && value > head -> next -> data)
head = head -> next;
temp -> next = head ->next->prev;
head -> next = temp -> prev;
while (head -> prev != NULL)
head = head -> prev;
}
Try this:
#include <stdio.h>
#include <stdlib.h>
struct node{
int data;
struct node *prev,*next;
} *head = 0;
void insert(int value){
struct node* temp = (struct node*) malloc (sizeof (struct node));
//int value;
//printf("Enter an element");
//scanf("%d",&value);
temp -> data = value;
temp -> next = 0;
temp -> prev = 0;
if(head == 0) {
// no head, make temp the head
head = temp;
} else if(value > head->data) {
// put temp in front of the head
temp->next = head;
head->prev = temp;
head = temp;
} else {
// put temp after the head
struct node *this = head;
struct node *prev = 0;
while(this && this->data > value) {
prev = this;
this = this->next;
}
temp->next = this;
temp->prev = prev;
prev->next = temp;
if(this) {
this->prev = temp;
}
}
}
int main() {
insert(1);
insert(3);
insert(4);
struct node *t = 0;
for(t = head; t; t = t->next) {
printf("%d\n", t->data);
}
}
This one compiles and sorts in descending value. Note I commented out your scanf
and made insert take a parameter.
the space you malloc is not enough.
change
struct node* temp = (struct node*) malloc (sizeof (struct node*));
to
struct node* temp = (struct node*) malloc (sizeof (struct node));
As a start, think about these two lines and what happens if head == NULL:
if(value < head->data || head == NULL){
temp->next = head->next;
Specifically what is head->next?
There are two core problems I see.
You are not allocating sufficient space for a node struct. sizeof(struct node *) returns the size of a node pointer, not a node. This:
struct node* temp = (struct node*) malloc (sizeof (struct node*));`
... should be this:
struct node* temp = (struct node*) malloc (sizeof (struct node));
Be careful with pointers:
if (value < head -> data || head == NULL)
... what is the value of head->data if you haven't initialized head? (e.g. it is still NULL). Your program will fetch data from address NULL with an offset for field data. Address NULL is not valid / is part of protected memory space, your OS won't like this :).
You should first check if head is NULL. If it is, then you can't reference fields of head as they are invalid (in any situation). Be careful with multi-part conditional expressions to check for struct pointer NULL presence prior to subsequent parts that reference struct fields, also.
Related
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;
}
The given program is not showing all the elements of the linked list.
I am having problem in identifying the error.
At first I initialized the head with a null value then made a temporary variable and assigned it an integer value and pointer to the next node.
Then I made an another node named temp1 and linked it with the head.
It will only be linked when "i" will be equal to 1.
Then equated temp1 to the next node and did the same.
//Linked list
//Inserting the nodes.
#include <stdio.h>
struct node
{
int n;
struct node *next;
};
struct node *head;
int main ()
{
int i, s, x, y;
i = 0;
struct node *temp;
struct node *temp1;
struct node *cur;
head = NULL;
scanf ("%d", &s); //No. of nodes.
while (i < s)
{
scanf ("%d", &x);
if (head == NULL)
{
temp = (struct node *) malloc (sizeof (struct node));
temp->n = x;
temp->next = NULL;
head = temp;
}
else
{
temp = (struct node *) malloc (sizeof (struct node));
temp->n = x;
temp->next = NULL;
temp1 = temp;
if (i == 1)
{
head->next = temp1;
}
temp1 = temp1->next; //Assigning the next node.i.e. NULL value
}
i = i + 1;
}
cur = head;
while (cur != NULL)
{
printf ("%d", cur->n);
cur = cur->next;
}
return 0;
}
Check the following changed section
{
temp = (struct node *) malloc (sizeof (struct node));
temp->n = x;
temp->next = NULL;
head = temp;
temp1 = head;
}
else
{
temp = (struct node *) malloc (sizeof (struct node));
temp->n = x;
temp->next = NULL;
temp1->next = temp;
temp1 = temp1->next; //Assigning the next node.i.e. NULL value
}
Instead of relying on
if (i == 1) {
head->next = temp1;
}
I assign head on temp1 while creating the head, which is meant to be happen only first time.
There were also some linkage issues in your else portion.
You lose nodes beyond the first two, since you never link them to the list. Use meaningful names for variables: rename temp1 to tail and initialize it to NULL in the beginning. Then the loop body becomes:
if (scanf(" %d", &x) != 1) {
// FIXME: handle error
}
temp = malloc(sizeof(*temp));
temp->n = x;
temp->next = NULL;
if (tail == NULL) {
head = temp;
} else {
tail->next = temp;
}
tail = temp;
++i;
(Untested.)
Rationale: You want to add new nodes to the end (tail) of the list. The easiest way is to keep track of the tail in an appropriately-named variable, and simply link every node to tail->next instead of convoluted logic like checking for the node count, etc. The only special case is the empty list, i.e., both head and tail are NULL, and the difference is just one line, so don't duplicate the whole block of code to set up the new node.
For starters you have to include the header <stdlib.h>.
The problem is in this statement
temp1 = temp;
if i is not equal to 1 then after this statement
temp1 = temp1->next;
temp1 becomes equal to NULL.
So all other nodes are not added to the list because there is a cycling
temp1 = temp;
//...
temp1 = temp1->next;
Change the loop the following way
while (i < s)
{
scanf ("%d", &x);
if (head == NULL)
{
temp = (struct node *) malloc (sizeof (struct node));
temp->n = x;
temp->next = NULL;
head = temp;
temp1 = head;
}
else
{
temp = (struct node *) malloc (sizeof (struct node));
temp->n = x;
temp->next = NULL;
temp1->next = temp;
temp1 = temp;
}
i++;
}
Pay attention to that you should declare variables in a block scope where they are used. Otherwise the program will be unreadable.
The approach you are using can be called as an Java approach.
In C the program can look much simpler. For example
#include <stdio.h>
#include <stdlib.h>
struct node
{
int n;
struct node *next;
};
struct node *head;
int main( void )
{
struct node **temp = &head;
size_t n = 0;
scanf( "%zu", &n );
for ( size_t i = 0; i < n; i++ )
{
*temp = (struct node *) malloc ( sizeof ( struct node ) );
int value = 0;
scanf ( "%d", &value);
( *temp )->n = value;
( *temp )->next = NULL;
temp = &( *temp )->next;
}
for ( struct node *cur = head; cur != NULL; cur = cur->next )
{
printf ("%d -> ", cur->n );
}
puts( "NULL" );
return 0;
}
Its output might look like
1 -> 2 -> 3 -> NULL
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.
So this is a very simple program to create and display a linked list. Here I'm getting caught in the display loop, and I'm seeing infinite '2->2->2->...' on screen.
After debugging, I can see that my program ALWAYS goes into the if statement of insertNode() whereas it should only go there ONCE i.e. when the linked list is initialized.
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node * next;
};
struct node * head = NULL;
struct node * curr = NULL;
void insertNode(struct node * temp2) {
if (head == NULL) {
head = temp2;
head->next = NULL;
}
else {
temp2->next = head;
head = temp2;
}
}
void display() {
curr = head;
while (curr->next != NULL)
{
printf("%d->",curr->data);
curr = curr->next;
}
}
void main() {
struct node * temp = (struct node *) malloc (sizeof(struct node));
temp->data = 5;
insertNode(temp);
temp->data = 6;
insertNode(temp);
temp->data = 1;
insertNode(temp);
temp->data = 2;
insertNode(temp);
display();
}
You should allocate and create new node for each data when inserting it in the linked list.
void main() {
struct node * temp = (struct node *) malloc (sizeof(struct node));
temp->data = 5;
insertNode(temp);
temp = malloc (sizeof(struct node));
temp->data = 6;
insertNode(temp);
temp = malloc (sizeof(struct node));
temp->data = 1;
insertNode(temp);
temp = malloc (sizeof(struct node));
temp->data = 2;
insertNode(temp);
display();
}
As you are using same node to add as multiple nodes, its making the circular list.
Your insertNode() looks ok.
You are setting next of temp2 to head, and then head to temp2. So in fact next node of temp2 is temp2, that's why you have infinite loop.
In you main you have one pointer to the temp and you continue inserting the same node and it ends up pointing to itself. You now have a circular list that's why you have an infinite loop.
You are getting an infinite loop because you only have one node. Doing temp->data = 5; and then temp->data = 6; does not create a new node. So when you add the same node into the list again, the next pointer in the node points to itself. So your while loop in display never terminates, because the next node is always the current node.
This question already has answers here:
pointer to a pointer in a linked list
(2 answers)
Closed 9 years ago.
Yesterday I was trying to implement a linked list and although it worked and I "sort of" understand, it fried my brain a little bit.
What is wrong with function addNode() here?
#include <stdio.h>
struct Node
{
int value;
struct Node *next;
};
struct Node *createList();
void addNode(struct Node* head, int value); // Adds Node directly after head
void viewList(struct Node *head); // Outputs list starting from head
int main()
{
struct Node *head = createList();
addNode(head, 10);
addNode(head, 8);
addNode(head, 23);
addNode(head, 5);
addNode(head, 4);
addNode(head, 4100);
viewList(head); // I didn't upload here to save space
return 0;
}
struct Node *createList()
{
struct Node *head = (struct Node *) malloc(sizeof(struct Node));
head = NULL;
return head;
}
void addNode(struct Node* head, int value)
{
if(head == NULL)
{
struct Node *tmp = (struct Node *) malloc(sizeof(struct Node));
tmp->value = value;
tmp->next = head;
head = tmp;
}
else
{
struct Node *newNode = (struct Node *) malloc(sizeof(struct Node));
newNode->value = value;
newNode->next = head;
head = newNode;
}
}
The reason I am confused is because that version of add node did not work whilst this one did...
void addNode(struct Node** head, int value)
{
if(*head == NULL)
{
struct Node *tmp = (struct Node *) malloc(sizeof(struct Node));
tmp->value = value;
tmp->next = *head;
*head = tmp;
}
else
{
struct Node *newNode = (struct Node *) malloc(sizeof(struct Node));
newNode->value = value;
newNode->next = *head;
*head = newNode;
}
}
and that was called in the main function using an amperand in front of the head node pointer
addNode(&head, 10);
The thing that also baffles me is this. I have written some practise functions that accepts a pointer in the parameter list and within the function, modifies what the pointer is pointing to. I never had to use this **pointer syntax.
It has to do with that parameters are passed by value. So in the first, non-working version, the pointer to head is passed by value so the variable is a local variable inside the function. Changes to local variables are not visible outside the function when the function returns.
However, in the second version you pass the pointer by reference, so the function knows where in memory the actual pointer is and can store directly in that memory.
ASCII-diagram time:
Lets say you have the following three variables:
int value1;
int *pointer1 = &value1;
int **pointer2 = &pointer1;
The memory for the variables look something like this:
+----------+ +----------+ +--------+
| pointer2 | --> | pointer1 | --> | value1 |
+----------+ +----------+ +--------+
So pointer2 points to pointer1, and pointer1 points to value1.
Using the dereference operator * on pointer2 will get the value of what pointer2 points to, i.e. pointer1.
Stylistic (don't repeat yourself) ::
void addNode(struct Node** head, int value)
{
if(*head == NULL)
{
struct Node *tmp = (struct Node *) malloc(sizeof(struct Node));
tmp->value = value;
tmp->next = *head;
*head = tmp;
}
else
{
struct Node *newNode = (struct Node *) malloc(sizeof(struct Node));
newNode->value = value;
newNode->next = *head;
*head = newNode;
}
}
You don't need the if/else ::
#include <stdlib.h>
void addNode(struct Node **head, int value)
{
struct Node *newNode = malloc(sizeof *newNode);
if ( !newNode) { error(); return;}
newNode->value = value;
newNode->next = *head; // Could be NULL, but we need a NULL anyway in that case
*head = newNode;
}
This here will not work well
struct Node *createList()
{
struct Node *head = (struct Node *) malloc(sizeof(struct Node));
head = NULL;
return head;
}
after you allocate a node and have head pointing to it you set head to point to NULL.
Here it is:
You have a bug with createList
struct Node *createList()
{
struct Node *head = malloc(sizeof(*head));
head->value = 0; //< Probably you want this
head->next = NULL; //< You definitively wanted this
return head;
}
If you are adding nodes to the tail of the list, then addNode would look like:
void addNodeLast(struct Node* head, int value)
{
struct Node *tailNode;
struct Node *newNode;
newNode = malloc(sizeof(*newNode));
newNode->value = value;
newNode->next = NULL;
// Find the last node in the list
for (tailNode = head; tailNode->next; tailNode = tailNode->next);
tailNode->next = head->next;
}
If you are inserting nodes after the head:
void addNodeAfterHead(struct Node* head, int value)
{
struct Node *newNode;
newNode = malloc(sizeof(*newNode));
newNode->value = value;
newNode->next = head-next;
head->next = newNode;
}
If you are changing the head (making new head every time):
Node *addNodeNewHead(struct Node* head, int value)
{
struct Node *newNode;
newNode = malloc(sizeof(*newNode));
newNode->value = value;
newNode->next = head;
return newNode;
}
...
Node * head = createList();
head = addNodNewHead(head, 3);
head = addNodNewHead(head, 5);