singly linked list operation insert at a particular position - c

I wrote a program to perform singly linked list operation insert at a particular position now there is no nodes at the moment , when I give the the input: 3 to the question enter the position to be inserted it shows runtime error
void insert_pos()
{
struct node * temp, *loc;
int item,pos,len;
printf("enter the position to be insertd :");
scanf("%d", &pos);
if (pos == 1)
{
insert_beg();
}
else
{
len = length();
if (start == NULL)
{
insert_beg();
}
else if (pos > len)
{
insert_end();
}
else
{
newnode = (struct node *)malloc(sizeof(struct node));
printf("enter the data :");
scanf("%d", &item);
newnode->data = item;
int i;
temp = start;
loc = temp->next;
for (i = 1; i < pos - 1; i++)
{
temp = temp->next;
loc = loc->next;
}
temp->next = newnode;
newnode->next = loc;
}
}
}
int length()
{
int k = 1;
struct node * temp;
while (temp->next != NULL)
{
temp = temp->next;
k++;
}
return k;
}
out put
1.insert # beg
2.insert # end
3.insert # perticular pos
4.display
5.exit
enter your option :3
enter the position to be inserted :3
now a window pops up saying debug error
pls help me with it

the problem was here the temp was Uninitialized
int length()
{
int k = 1;
struct node * temp;
while (temp->next != NULL)
{
temp = temp->next;
k++;
}
return k;
}
the fix was to assign temp = start;
corrected program
int length()
{
int k = 1;
struct node * temp;
temp=start; // start is a global variable
while (temp->next != NULL)
{
temp = temp->next;
k++;
}
return k;
}
thanks every one for the tips !!!

Related

Why does my program is terminating abruptly?

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
static int COUNT = 1;
typedef struct node NODE;
struct node
{
int data;
NODE *next;
};
NODE *START = NULL;
NODE *create_node() {
NODE *n = malloc(sizeof(NODE));
n->data = 0;
n->next = NULL;
return n;
}
void insert_at_beginning() {
NODE *n, *temp;
n = create_node();
printf("Enter a number: ");
scanf("%d",&n->data);
if(START == NULL) {
START = n;
} else {
temp = START;
START = n;
n->next = temp;
}
COUNT++;
printf("Successfully Inserted!\n");
}
void insert_at_a_position() {
int position, count;
NODE *n, *temp, *t;
printf("Enter position at which you want to insert: ");
scanf("%d", &position);
if(COUNT<position) {
printf("Out of Bound! Please try again.\n");
} else
{
count = 1;
n = create_node();
printf("Enter a number: ");
scanf("%d",&n->data);
temp = START;
while(count != position) {
count++; //To stoping the variable at given position
t = temp; //Getting Previous node where we will set link to n
temp = temp->next; //getting next element whose link will be attached to n to form complete linked list
}
n->next = temp;
t->next = n;
COUNT++;
printf("Successfully Inserted!\n");
}
}
void insert_at_end() {
NODE *n, *temp;
temp = START;
n = create_node();
printf("Enter a number: ");
scanf("%d", &n->data);
while(temp!=NULL) {
printf("I am here!");
temp = temp->next;
}
temp->next = n;
COUNT++;
printf("Successfully Inserted!\n");
}
void display() {
NODE *temp;
temp = START;
while (temp!=NULL)
{
printf("%d", temp->data);
temp = temp->next;
}
}
int main() {
int ch;
printf("1.Insert at beginning\n2.Insert at mid\n3.Insert at end\n4.Delete from beginning\n5.Delete from position\n6.Delete from end\n7.Display");
printf("\nEnter your choice: ");
scanf("%d", &ch);
while (ch!=0)
{
switch(ch) {
case 1:
insert_at_beginning();
break;
case 2:
insert_at_a_position();
break;
case 3:
insert_at_end();
break;
case 4:
display();
break;
default:
printf("Wrong Choice!!");
}
printf("Enter Your Choice: ");
scanf("%d",&ch);
}
return 0;
}
insert_at_beginning and insert_at_end is working perfectly but insert_at_end and display function is showing problem
In display function: Program goes in infinite loop
In insert_at_end: Program goes through while loop (i.e., printing "I am here" node number of time) but then it terminates abruptly without assigning the value in the given position.
For starters it is a bad idea to declare the initial pointer to nodes as a global variable and when function depends on global variables.
Also it is unclear why the static variable COUNT is initialized by 1 instead of 0 when initially the list is empty.
static int COUNT = 1;
It should be initialized by zero
static int COUNT = 0;
insert_at_beginning and insert_at_end is working perfectly
You are wrong. The function insert_at_end is invalid.
void insert_at_end() {
NODE *n, *temp;
temp = START;
n = create_node();
printf("Enter a number: ");
scanf("%d", &n->data);
while(temp!=NULL) {
printf("I am here!");
temp = temp->next;
}
temp->next = n;
COUNT++;
printf("Successfully Inserted!\n");
}
For example the function can be called when the list is empty that is when the pointer START is equal to NULL. In this case the pointer START is not changed in the function.
Moreover even if the pointer START is not equal to NULL then after this loop
while(temp!=NULL) {
printf("I am here!");
temp = temp->next;
}
the pointer temp is equal to NULL. So the next statement
temp->next = n;
invokes undefined behavior.
The function can be written at least the following way
void insert_at_end() {
NODE *n;
n = create_node();
printf("Enter a number: ");
scanf("%d", &n->data);
if ( START == NULL )
{
START = n;
}
else
{
NODE *temp = START;
while ( temp->next !=NULL )
{
printf("I am here!");
temp = temp->next;
}
temp->next = n;
COUNT++;
printf("Successfully Inserted!\n");
}
}
As for the function insert_at_a_position then there is a confusion relative to the global variable COUNT. As I pointed out initially when the list is empty COUNT is equal to 1. So a valid position can be less than COUNT. Take into account that the user can enter for example the value of position equal to 0.
So for example this if statement
if(COUNT<position) {
printf("Out of Bound! Please try again.\n");
} else
should be rewritten like
if ( !( position < COUNT ) ) {
printf("Out of Bound! Please try again.\n");
} else
Also when the user will enter 0 then this loop
count = 1;
//...
while(count != position) {
//...
can invoke undefined behavior.
And again if the list is empty that is START is equal to NULL then START is not changed in the function.
Also if the user entered the position equal to 1 then in this case the while loop will not executed. On this case the pointer t has indeterminate value because it was not initialized outside the loop. So this statement
t->next = n;
again invoke undefined behavior.
The function can be defined the following way
void insert_at_a_position() {
int position;
printf("Enter position at which you want to insert: ");
scanf("%d", &position);
if( !( position < COUNT ) ) {
printf("Out of Bound! Please try again.\n");
} else
{
NODE *n = create_node();
printf("Enter a number: ");
scanf("%d",&n->data);
NODE *temp = START;
NODE *prev = START;
while( position-- != 0 )
{
prev = temp;
temp = temp->next;
}
n->next = temp;
if ( prev == NULL ) START = n;
else prev->next = n;
COUNT++;
printf("Successfully Inserted!\n");
}
}
You are dereferencing a NULL pointer.
while(temp!=NULL) {
printf("I am here!");
temp = temp->next;
}
temp->next = n; // temp is NULL here!!
You can change the loop condition to:
while (temp->next != NULL) {
But before you do that, you should check that temp is not NULL:
temp = START;
if (temp == NULL) {
insert_at_beginning();
return;
}
Aside: it is more standard to just write:
if (!temp)
than
if (temp == NULL)

Having trouble with linked lists, program will not print the elements

I am supposed to do an assignment in C programming language. It includes linked lists and reading user input from the console.
The user inputs numbers into the console, for example ( 1 3 5 7 0 ), which are added, one by one, to the beginning of the linked list. 0 marks the end of the transition. This is what the linked list should look like after the first part: 7 5 3 1
I need to code two different functions that will delete different elements of the linked list.
First function deletes all elements from the list that have the value that you input, and second function deletes the element on the position that the user inputs, if it exists.
At the end, you should print the list.
I've written the the first function correctly, and I am sure about it, with the second function (the one that deletes elements on a certain position) I had some trouble. I made a simple function that counts how many nodes are there in total, so if someone puts a number larger than the amount of nodes, a message would pop up. I also used that function to make a for loop and used it as a limit when searching for the element on a certain position, if that makes any sense. The program also won't print anything, I have no idea why.
typedef struct Element Element;
struct Element
{
int number;
Element *next;
};
Element *addnewN(int number)
{
Element *newN = (Element*)malloc(sizeof(Element));
newN->number = number;
newN->next = NULL;
return newN;
}
Element *add_on_beginning(Element *head, Element *newN)
{
newN->next = head;
return head;
}
Element* delete_value(Element* head, int value)
{
Element *before = NULL;
Element *temp = head;
Element *newNhead = head;
while(temp != NULL)
{
if(temp->number == value)
{
if(before == NULL)
{
newNhead = temp->next;
free(temp);
temp = newNhead;
}
else
{
before->next = temp->next;
free(temp);
temp = before->next;
}
}
else
{
before = temp;
temp = temp->next;
}
}
return newNhead;
}
int counter(Element *head)
{
int count = 0;
Element *temp = head;
while(temp != NULL)
{
count++;
temp = temp->next;
}
return count;
}
Element* delete_on_position(Element* head, int position)
{
int limit = counter(head);
Element *temp = head;
Element *newNhead = head;
Element *before = NULL;
if(position > limit)
{
printf("Error.\n");
}
for(int i = 0; i < limit; i++)
{
if(position == 0)
{
newNhead = temp->next;
free(temp);
temp = newNhead;
}
else if(position == i)
{
before->next = temp->next;
free(temp);
temp = before->next;
}
else
{
before = temp;
temp = temp->next;
}
}
return head;
}
void printElement(Element *element)
{
printf("%d ", element->number);
}
void printList(Element *head)
{
Element *temp = head;
while(temp != NULL)
{
printElement(temp);
temp = temp->next;
}
}
void menu()
{
printf("\t MENU \n");
printf("1. Delete all elements from the list that have the value that
you input.\n");
printf("2. Delete the element on the position, if it exists.\n");
printf("3. Print the list. \n");
printf("4. Exit \n");
}
int main()
{
Element *head = NULL;
int i = 0;
int arr[1000];
char temp;
int x;
int y;
printf("Input the numbers you want: \n");
while(temp != '\n')
{
scanf("%d%c", &arr[i], &temp);
if(arr[i] == 0)
{
break;
}
head = add_on_beginning(head, addnewN(arr[i]));
i++;
}
menu();
while(1)
{
scanf("%d", &x);
switch(x)
{
case 1:
{
scanf("%d", &y);
head = delete_value(head, y);
break;
}
case 2:
{
scanf("%d", &y);
head = delete_on_position(head, y);
break;
}
case 3:
{
printList(head);
break;
}
case 4:
{
return 0;
}
}
}
return 0;
}
What you are supposed to get would be for example:
Input: 2 4 5 8 5 0 (in one line), and in one line each:
2
2
1
5
3
Output: 2 8
When debugged, the code does not show any errors.
add_on_beginning is not returning the correct value. It should return the node that was added, since it's the new head of the list. Nothing else will work correctly because of that, because head will always be NULL.
Element *add_on_beginning(Element *head, Element *newN)
{
newN->next = head;
return newN;
}

Simplest Linked List Creation and Printing Data

The following is a simple code segment in C to create a linked list and print all elements contained in the list.
User is asked to input integer data till a zero is entered which marks the termination of user input; Once data is saved in the linked list, the program prints all elements stored in the list and then completes its execution.
I can't make it run, every time it gives a "Segmentation fault" error, please check and tell me where I'm wrong (using gcc 4.8.2)
Code :
struct node
{
int data;
struct node * next;
};
struct node * createLinkedList()
{
int x;
struct node * start;
start = NULL;
printf("Input 0 to end, Insert elements :\n");
for(scanf("%d", &x); x ;scanf("%d", &x))
{
struct node * temp = (struct node *) malloc(sizeof(struct node));
if (temp)
{
temp->data = x;
temp->next = NULL;
if(start == NULL) {
start = temp;
} else {
start->next = temp;
start = temp;
}
}
}
return start;
}
void printLinkedList(struct node * start)
{
if (start == NULL) {
printf("Linked List is empty!\n");
} else {
printf("\nPrinting Linked List : \n");
struct node * s;
s = start;
while(s != NULL)
{
printf("%d\n", s->data);
s = s->next;
}
}
}
int main(int argc, char const *argv[])
{
struct node * start;
start = NULL;
start = createLinkedList();
printLinkedList(start);
return 0;
}
This part of code
if(start == NULL) {
start = temp;
} else {
start->next = temp;
start = temp;
}
is invalid. There has to be
if(start == NULL) {
start = temp;
} else {
temp->next = start;
start = temp;
}
Also you need to have a function that deletes all nodes of the list.

deleting a node in the middle of a linked list

I have written a piece of code that uses linked lists. I get the user to enter a couple of numbers and then ask the user to enter the index of the digit he wishes to delete. I did some research and found out that i need to check whether the next node is the one I want to delete, then have 2 temp pointers point to the current node and the next node(which is the one i want to delete), then assign the next node of the first temp pointer to the next node of the second temp pointer then finally free the second temp pointer. Here is my code:
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int item;
struct node *next;
}ListNode;
void print(ListNode *head);
int deleteNode(ListNode **ptrHead, int index);
int main()
{
int n;
int remove;
ListNode *head = NULL;
ListNode *temp = NULL;
printf("Enter a value: ");
scanf("%d", &n);
while (n != -1)
{
if (head == NULL)
{
head = malloc(sizeof(ListNode));
temp = head;
}
else
{
temp->next = malloc(sizeof(ListNode));
temp = temp->next;
}
temp->item = n;
temp->next = NULL;
printf("Enter a value: ");
scanf("%d", &n);
}
printf("Enter index to remove: ");
scanf("%i", &remove);
while (remove != -1)
{
deleteNode(&head, remove);
print(head);
printf("Enter index to remove: ");
scanf("%i", &remove);
}
while (head != NULL)
{
temp = head;
head = head->next;
free(temp);
}
head = NULL;
return 0;
}
int deleteNode(ListNode **ptrHead, int index)
{
int count = 0;
ListNode* temp1 = NULL;
ListNode* temp2 = NULL;
while (count <= index)
{
if (index == 0)
{
temp2 = (*ptrHead)->next;
free((*ptrHead));
(*ptrHead) = temp2;
return 0;
break;
}
if (count+1 == index)//checking for the node ahead
{
temp1 = (*ptrHead);
temp2 = (*ptrHead)->next;//the one to free
temp1->next = temp2->next;
free(temp2);
return 0;
break;
}
(*ptrHead) = (*ptrHead)->next;
count++;
}
return -1;
}
void print(ListNode *head){
if (head == NULL)
{
return;
}
while (head != NULL)
{
printf("%i\n", head->item);
head = head->next;
}
}
So for example if i enter 1 2 3 4 5 -1, the linked list will contain 1 2 3 4 5. Then if i enter 0 for the index to remove, the program will print out 2 3 4 5. This works whether I enter 0 or 1. However, when I enter the indexes 2 and above, it gives me weird outputs like for example if I set the linked list as 1 2 3 4 5, and enter the index 2 to remove, by rights it should output 1 2 4 5, but instead it outputs 2 4 5, I have no idea whats going on, please point me in the right direction.
In deleteNode you use the actual headpointer to traverse the list. As you loop through the list you move the actual head! You should only modify (*ptrHead) when you delete the first element.
I suggest that you copy *ptrHead to a local variable and use the local variable to traverse the list.
I've highlighted the important lines with comments starting with // ***
int deleteNode(ListNode **ptrHead, int index)
{
int count = 0;
ListNode* temp1 = NULL;
ListNode* temp2 = NULL;
ListNode* traverse = *ptrHead; // *** make a copy that we can use to traverse the list
while (count <= index)
{
if (index == 0)
{
temp2 = (*ptrHead)->next;
free((*ptrHead));
(*ptrHead) = temp2; // *** Keep this line as it is to correctly handle deletion of index 0.
return 0;
break;
}
if (count+1 == index)//checking for the node ahead
{
temp1 = traverse; // *** Use local copy of pointer
temp2 = traverse->next;//the one to free // *** Use local copy of pointer
temp1->next = temp2->next;
free(temp2);
return 0;
break;
}
traverse = traverse->next; // *** Use local copy of pointer
count++;
}
return -1;
}
Find the modified deleteNode function (handles boundary conditions also , if we are trying to delete an index which is more then the list length)
int deleteNode(ListNode **ptrHead, int index)
{
int count = 0;
ListNode* temp1 = NULL;
ListNode* temp2 = NULL;
temp1 = (*ptrHead);
while((temp1 != NULL) && (count <= index))
{
if (index == 0)
{
temp2 = temp1->next;
free(temp1);
(*ptrHead) = temp2;
return 0;
}
if ((count+1 == index) && (temp1->next != NULL))
{
ListNode*temp = NULL;
temp = temp1->next;
temp2 = temp->next;
temp1->next = temp2;
free(temp);
return 0;
}
temp1 = temp1->next;
count++;
}
return -1;
}

How to combine in one loop serial numbers and null?

I'm busy with implementation of singly linked list and have 2 functions: insert_back and insert_after.
Here is the listing of them:
void insert_back(int data)
{
node *temp1;
temp1 = (node*)malloc(sizeof(node));
temp1 = head;
while (temp1->next != NULL) {
temp1 = temp1->next;
}
node *temp;
temp = (node*)malloc(sizeof(node));
temp->data = data;
temp->next = NULL;
temp1->next = temp;
}
void insert_after(int pos, int data)
{
node *temp1;
temp1 = (node*)malloc(sizeof(node));
temp1 = head;
for (int i = 1; i < pos; i++) {
temp1 = temp1->next;
if (temp1 == NULL) {
return;
}
}
node *temp;
temp = (node*)malloc(sizeof(node));
temp->data = data;
temp->next = temp1->next;
temp1->next = temp;
}
As you can see they are almost the same and for insert back I want to write insert_after(null, 10). I can solve it by adding if condition and choose one of the loops, but it's not my aim.
Is it possible somehow to use one while or for loops together for serial numbers and null?
Also I see that param int pos is int. Should I use 0 instead of null?
You unnecessarily allocate memory in the following lines.
temp1 = (node*)malloc(sizeof(node));
temp1 = head;
This allocated memory will leak as you overwrite the returned address in temp1. You just need temp1 to walk over the list, so there is also no need to allocate any node itself. temp1 can point to any node.
I've taken the liberty to kind of from scratch write a routine doing both things in one go. If pos < 0 it will add the element to the end of the list, otherwise it will add it after the pos-th element, where the first element corresponds with pos == 1. If pos == 0 the element is added at the start of the list.
Also a small main is added to test the routine. new_node has been added to test if memory is not exhausted.
#include <stdlib.h>
#include <stdio.h>
typedef struct node
{
struct node * next;
int data;
} node;
node * head = NULL;
node * new_node(void)
{
node * result = malloc(sizeof(*result));
if (result == NULL)
{
fprintf(stderr, "Out of memory.\n");
exit(10);
}
return result;
}
void insert_after(int pos, int data)
{
node *walk, * prev;
int i;
prev = NULL;
walk = head;
for (i = 0; walk != NULL && i != pos; i++)
{
prev = walk;
walk = walk->next;
}
if (i != pos && pos > 0)
{
fprintf(stderr, "Location not found.\n");
exit(9);
}
else
{
walk = new_node();
walk->data = data;
if (prev == NULL)
{
walk->next = head;
head = walk;
}
else
{
walk->next = prev->next;
prev->next = walk;
}
}
}
int main(void)
{
int i;
node * wlk;
for (i = 0; i < 10; i++)
{
insert_after(-1, i);
}
for (i = 0; i < 10; i++)
{
insert_after(3, i+10);
}
for (wlk = head; wlk != NULL; wlk = wlk->next)
{
printf("%d\n", wlk->data);
}
return 0;
}
Since you are testing for the end of the chain with insert_after(pos,...) anyway, you could go for:
void insert_after(int pos, int data)
{
node *temp1= head;
for (int i=1; i<pos; i++) {
if (temp1->next==NULL) {
if (pos==INT_MAX)
break; // pos of INT_MAX means insert at end
// so we continue with this last item and append
else
return; // pos higher than length of chain
}
temp1 = temp1->next;
}
...
}
Or slightly more compact:
void insert_after(int pos, int data)
{
node *temp1= head;
for (int i=1; i<pos && temp1->next!=NULL; i++) {
temp1 = temp1->next;
}
if (temp1->next==NULL && pos!=INT_MAX)
return; // pos higher than length of chain, except for
// INT_MAX (for that we just want to continue)
...
}
Then you could use
void insert_back(int data)
{
insert_after(INT_MAX, data);
}

Resources