Linked List element insertion at nth location - c

I am trying to implement linked list in C and I have two different functions that are supposed to insert elements in the beginning and at nth position. My program crashes when it goes to the part where it starts executing the function to insert at nth position. Can someone please point out my mistake. Also the compiler tends to skip the last scanf statement (marked in the comments).
/****************************************************************
*Date: 12/30/2016
*This program adds an element to the beginning and nth position
*of a linked list and then displays the elements in the list
*****************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
struct node
{
int data;//Refers to the data part of the linked list
struct node* next;//Refers to the pointer which points to the next element
};
/*************************************************************************************
Description : This function is used to print the elements in the linked list
Input : Pointer to the beginning of the linked list
Output : N/A
*************************************************************************************/
void PrintElements(struct node *start)
{
if(start==NULL)//If the list is empty
printf("List is empty");
else
{
while(start!=NULL)
{
printf("%d ",start->data);
start=start->next;
}
}
}
/*************************************************************************************
Description : This function is used to insert elements in the beginning of the
linked list
Input : Element to be inserted
Output : N/A
*************************************************************************************/
struct node* InsertElementInTheBeginning(struct node *start, int x)
{
struct node *new_node=(struct node*)malloc(sizeof(struct node));
if(new_node==NULL)
{
printf("Memory allocation failed");
return start;
}
new_node->data=x;
new_node->next=start;
start=new_node;
return new_node;
}
/*************************************************************************************
Description : This function is used to insert elements in the nth position of the
linked list
Input : Element and position to be inserted, pointer to beginning of linked
list
Output : N/A
*************************************************************************************/
struct node* InsertElementAtN(struct node *start,int x, int n)//Here the starting position for the linked list is assumed to be 1
{
int i;
struct node* new_node=(struct node*)malloc(sizeof(struct node));
if(new_node==NULL)
{
printf("Memory allocation failed");
return start;
}
new_node->data=x;
new_node->next=NULL;
if(n==1)
{
new_node->next=start;
start=new_node;
return start;
}
struct node *ptr;
ptr=start;
for(i=0;i<n-2;i++)
{
ptr=ptr->next;
}
new_node->next=ptr->next;
ptr->next=new_node;
return start;
}
int main()
{
int x, n;
struct node *HEAD;
struct node *ptr;
HEAD=NULL; //Assigning HEAD to null when there are no elements in the list
ptr=NULL;
printf("\n\rEnter numbers to be inserted into the list\n Press q to quit\n");
while(scanf("%d",&x)==1)
{
HEAD=InsertElementInTheBeginning(HEAD,x);
PrintElements(HEAD);
printf("\n\rEnter numbers to be inserted into the list\n Press q to quit\n");
}
printf("\n\rEnter the number and position to be inserted");
scanf("%d %d",&x,&n);//The compiler always skips this scanf no clue why
HEAD=InsertElementAtN(HEAD, x, n);
PrintElements(HEAD);
//Freeing dynamic memory
while(HEAD!=NULL)
{
ptr=HEAD;
HEAD=ptr->next;
free(ptr);
}
return 0;
}

I've always found something like this to be easier for me to understand (I'm assuming your positions must be 1 or more based on your code, unlike the usual C convention of 0 or more):
struct node *insertValueAt(struct node *head, int value, int position) {
struct node *current;
if (head == NULL || position == 1)
return insertBefore(head, value);
for (current = head; position > 1 && current->next != NULL; position--)
current = current->next;
current->next = insertBefore(current->next, value);
return head;
}
Note that I used the name insertBefore, but your InsertElementAtTheBeginning does the same thing. The key to inserting a node N between to existing nodes A and B is to make A->next point to N that is returned from InsertElementAtTheBeginning(B, value).
Another thing to note is the unconditional insertion before a NULL node (i.e. at the beginning of an empty list or at the end of the list), regardless of the value of position because you can't insert an item at position 10 if you only have fewer than 4 items.

Add a getchar() after the first while loop in the main(). For explanation please check C: Multiple scanf's, when I enter in a value for one scanf it skips the second scanf.

you should check that ptr->next is not NULL.
for(i=0;i<n-2;i++)
{
if (ptr->next == NULL) return NULL;
ptr=ptr->next;
}

Related

Print first element of linked list in C lang

While teaching my self how to manage linked lists in C i came across some difficulties. I created a function getNode to create a list of 4 integers. Now i would like to printf the first element of the list, so that i can learn something new. Unfortunatelly, when i try to recall the head node of the list, the program prints the last node. When all code was in main() , there was no problems or what so ever, only when i got to factorize the code the dificulities mentioned have occured. It might be just lacking a pointer, or some sort of logical error. Any help apreciated! thanks
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct list
{
int x;
struct list *next;
}list;
list *getNode()
{
int marker = 0;
int base;
list *head, *current;
head=current=NULL;
while (marker < 4)
{
printf("wprowdz liczbe dla NodE o markerze: %d \n", marker + 1);
scanf("%d", &base);
list *node = malloc(sizeof(list));
node->x = base;
node->next = NULL;
if (head == NULL)
{
current = head = node;
}
else
{
current = current->next = node;
}
marker++;
}
return current;
}
void printNode(list *head)
{
printf("this shoud print the first element of linked list :");
printf("%d", head->x);
}
int main()
{
list *start = getNode();
printNode(start);
}
My dear friend, in the function getNode you need to return the head pointer not the current pointer. The head pointer points at the first node but the current node is pointing at the last node because you are updating the current node everytime while loop is executed.
So, we need to return the head pointer in order to traverse through the linked list or print the first element. Hope you get it !! Cheers, feel free to ask questions

What should I do so that the last node in the linked list participates in bubble sort?

I have written a linked list program and I ought to program a bubble sorting function, but the last node seems to not participate in the bubble sort. I guess that's because the pointer moves to NULL and rejects the last node data. Can you please suggest me a way to sort the linked list in any other way, that would also help.
My code is:
#include<stdio.h>
#include<stdlib.h>
typedef struct node_type{
int data;
struct node_type *next;
}node;
typedef node *list;
list head;
void traverse()
{
list temp;
temp=head;
printf("\nThe Data is: \n");
while(temp!=NULL)
{
printf("%d\n",temp->data);
temp=temp->next;
}
printf("\n\n");
}
void sort_list()
{
list new,ptr;
int temp;
for(new=head;new->next!=NULL;new=new->next)
{
for(ptr=new->next;ptr->next!=NULL;ptr=ptr->next)
{
if(new->data > ptr->data)
{
temp=new->data;
new->data=ptr->data;
ptr->data=temp;
}
}
}
traverse();
}
void main()
{
list temp,new;
head=NULL;
int n;
char ch;
temp=(list) malloc(sizeof(node));
printf("\nGive data: ");
scanf("%d",&temp->data);
head=temp;
printf("\n");
printf("Enter more data(y/n): ");
scanf("\n%c",&ch);
while(ch=='y')
{
new=(list) malloc(sizeof(node));
printf("Give data: ");
scanf("%d",&new->data);
temp->next=new;
temp=new;
printf("\nEnter more data(y/n): ");
scanf("\n%c",&ch);
}
temp->next=NULL;
traverse(head);
printf("\n\nDo you want to sort the Link-List(y/n): ");
scanf("\n%c",&ch);
if(ch=='y')
{
sort_list();
}
}
Input: 2 3 1 5 4
Output: 1 2 3 5 4
The inner loop of sort_list() is not considering the last node during sorting because of the condition ptr->next!=NULL in for loop. You should check it ptr with NULL:
for(ptr = new->next; ptr != NULL; ptr = ptr->next)
^^^^
There are several things that needs to be fixed.
The main function needs to have a return value of int not void.
There are calls to traverse that pass head as an argument, which will give an error. Either update the traverse function to except a list argument, or fix those calls.
The sort_list function's inner for loop's condition should end when ptr == NULL i.e.
for(ptr=new->next; ptr != NULL; ptr=ptr->next)
The function could be more defensive, if head happens to be NULL, the first for loop would cause a segmentation fault when new->next != NULL becomes evaluated. You could have an if statement at the beginning of the function to guard against this.
The last thing is since malloc is being used, make sure that memory is freed. You will need to iterate through the list and free each node.

ACCEPT ELEMENTS IN A LINKED LIST IN ASCENDING ORDER,but the display function prints the smallest number instead of the whole linked list

Accept elements in the linked list in ascending order and then i want to print the whole linked list but it prints only the first number and gives a run time error.similar code is available in data structures in c.
here t=start so that when the element less than the start node is entered then the address of the starting node is saved in the t pointer.
#include<stdio.h>
#include<stdlib.h>
//creation of a linked list
struct node
{
int data;
struct node *next;
};
void display(struct node *start); //function to display Linked list
int main()
{
struct node *start,*t,*r;
start=NULL;
t=start;
int n,num,i;
print("\n enter the number of elements");
scanf("%d",&num);
for(i=0;i<num;i++)
{
printf("\n enter the %d element",i);
scanf("%d",&n);
r=(struct node *)malloc(sizeof(struct node));//
r->data=n;
if(start==NULL || start->data>n)//if the element id the first element or the element is less than the current element
{
start=r;
start->next=t;
}
else
{
t=start;
while(t!=NULL)
{
if(t->data<n && (t->next==NULL || t->next->data>n))//element has to added in the end or else it should be added between the following elements
{
r->next=t->next;
t->next=r;
}
t=t->next;
}
}
}
display(start);
}
void display(struct node *start)
{
struct node *display;
display=start;
while(display!=NULL)
{
print("%d ",display->data);
display=display->next;
}
}
as your description suggests you have an issue when the inputed value is lower then the list head value, you want to place the allocated node at the start of the list and verify that this node now points to the previous head:
if( start == NULL || start->data > n )//if the element id the first element or the element is less than the current element
{
r->next = start; //1
start=r; //2
//start->next=t; //3
}
your newly allocated node r should now point to the next element which was previously your start
now you should move your start pointer to the head of the list which is r
your mistake:
in each loop iteration t will always point to NULL, due to the `t=t->next;' and 'while(t!=NULL)'.
in that case every time your if evaluates to true (current value should be placed at the start of the list), you are effectivly creating a new list where that node is the head.

Link Linked Lists in C

I am trying to create an (ordered) linked list of (ordered) linked lists. The list-of-list links are carried by the first nodes of its member lists. I am trying to achieve this via the following code, but my program crashes right after I try to insert the second node into the list of lists.
Here's a schematic of the data structure I am trying to construct:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
struct node{
int number;
struct node*next;
struct node*lsnext;
};
typedef struct node Node;
Node* insertValue(Node * list, int value);
void display(Node*);
Node* insertArr(Node * list, int value);
int main()
{
Node *globalList = NULL, *lists,*start,*save;
int nbrOfLists, listNo, nbrOfVal, valNo, val;
printf("\n Enter the number of lists:");
scanf("%d", &nbrOfLists);
if(nbrOfLists < 0)
return -1;
for(listNo = 0; listNo < nbrOfLists; listNo++)
{
printf("\n\n Enter the number of inputs to the list %d: \n ",listNo+1);
scanf("%d", &nbrOfVal);
lists = NULL;
for(valNo = 0; valNo < nbrOfVal; valNo++)
{
printf("Enter node value %d:", valNo+1);
scanf("%d", &val);
// Here we insert the value in both lists
lists= insertValue(lists, val);
globalList = insertValue(globalList, val);
}
start=lists;
if(listNo==0){
save=start;
}
start=start->lsnext;
printf("\n The list %d is: ",listNo+1);
display(lists);
}
printf("\n\n The final list is: ");
display(globalList);
printf("The first list is");
display(save);
printf("The second list is");
display(save->lsnext); // CRASHES HERE
return 0;
}
Node* insertValue(Node * list, int value)
{
Node *newNode, *m;
newNode = malloc(sizeof(Node));
newNode->number=value;
if(list == NULL)
{
newNode->next=NULL;
return newNode;
}
if(value < list->number)
{
newNode->next = list;
return newNode;
}
m = list;
while(m->next)
{
if(value < m->next->number)
break;
m = m->next;
}
newNode->next = m->next;
m->next = newNode;
return list;
}
void display(Node*nodex){
while(nodex)
{
printf("%d ->",nodex->number);
nodex=nodex->next;
}
}
What is causing my error?
Your insertArr() function is wrong. Even its signature is wrong. Instead of linking together the first nodes of existing lists, it creates a perpendicular list of separate nodes. Note in particular that it accepts a value where it needs instead to accept the head node of a list.
Moreover, even the circumstances under which you call that function are wrong. You seem to try to link the initial head nodes of each list, but the head node may change as you add values. You must wait until you have a full list before you know what its final head node is; only then can you link that list into your list of lists.
Edit: I had first asserted that your problem was failure to initialize the lsnext members of your nodes. That would be correct if your insertArr() function were actually accepting nodes created by insertValue() as its second argument, as it should, but it is not correct for the code presented. The actual problem is a consequence of the issue described in my first paragraph, that insertArr() creates a separate list of separate nodes. In particular, those separate nodes do not have their next pointers initialized.

trouble in with reverse viewing/search function in double linked list C programming

hey guys this is my first time doing double linked list so I'm not very sure what I'm doing here ,need some help to check the code,thanks, here is what I have done with comments included.
The functions I have done here are print,print reverse,count elements in the linked list,and search function to determine whether this node exist
void printListfow() //print the list in forward manner
{
CLR;
struct node *tmpval; //declare a temp storage
if(start==NULL) //if 1st node = null,then nth is inside,nth to print
{
printf("List is empty\n");
return;
}
tmpval=start; //assign the head/start to temp storage to retrieve data in 1st node
printf("List of customer details: \n");
while(tmpval!=NULL) //keep doing till it is NULL/the end
{
printf("%d ", tmpval->detail); //print the 'detail' which is in the node temp is pointing at
tmpval=tmpval->next; //assign next node to the temp storage so that it can be printed again
}
}
void printListrev() //print in reverse manner
{
CLR;
struct node *tmpval; //temp storage
if(start==NULL) //
{
printf("List is empty\n");
return;
}
tmpval=start; //assign start to tmpval to retrieve value
printf("List of customer details: \n");
tmpval=tmpval->prev //move backward and assign the data to tmpval
printf("%d",tmpval->detail) //print it
}
void count() //count total number of records
{ struct node *x;
x=start; //assign value of start to temp storage
int ctr=0; //initialize counter
while(x!=NULL)
{
x=x->next; //keep going to next node and then increase the counter
ctr++;
}
printf("Number of customer records are %d\n",ctr);
}
int getNode(node *tmp ,int cust) //when user wants to delete a customer ID and its details, this will search through the list,then if found,pass the value to another function for deletion
{
tmp=tmp->cust;
while(tmp!=NULL)
{
if(tmp->detail == cust) //check if detail[ID stored] is same as requested[cust]
{
return 1;
}tmp=tmp->next; //if not same,then move to next one
}return 0;
}
thanks!
In context to printListrev():
Unless this is a circular doubly linked list, in which case last element is preceded by the first, start would have previous element NULL. So, there is no point in accessing the previous field of start, as you do here:
tmpval=start;
...
tmpval=tmpval->prev;
You can keep another pointer to end of the list for this purpose.
Other alternatives include:
recursive function:
void printrev(struct node *s)
{
if (s == NULL)
return;
printrev(s->next);
printf("%d ", s->detail);
}
iterative function:
void printrev()
{
struct node *end;
for (end = start; end->next != NULL; end = end->next)
;
for (; end != NULL; end = end->prev)
printf("%d ", end->detail);
}
Your getNode is of limited use. Suppose, if you want to delete element, your getnode would only return whether, element is present or not. Say it is present, your deleteNode function would still have to iterate to the appropriate element in the list before deleting it.
This could be solved by getNode returning pointer to the node:
node *getNode(int x)
{
node *t;
for (t = start; t != NULL; t = t->next)
if (t->detail == x)
return t;
return t;
}
Now, you can code delete as follows:
void delNode(node *n)
{
n->prev->next = n->next;
n->next->prev = n->prev;
free(n);
}
And call as follows:
node *n;
if ((n = getNode(x)) != NULL)
delNode(n);
I've assumed that you struct is:
struct node {
int detail;
struct node *next;
struct node *right;
};
typedef struct node * node;
In printListrev() you are printing only one node not going reverse.
One major problem you are doing is in getNode() ,you are changing the address of a local pointer but the original pointer still points where it previously.
If so then how you are going to delete that node ,as you can't know the node address after this function returns.
Are you going to call the getNode() for all the node ,if so that is not a good if you have many nodes.

Resources