More linked lists in C - c

Before I begin I want to make it clear that I don't want the answer to my HOMEWORK problem, I would just like if someone could actually explain what exactly my instructor is asking for in this assignment (preferably a dumbed down version) and maybe a helpful push in the right direction. I'm having a lot of trouble with this topic and whenever I ask the instructor I find that he confuses me more than anything else.
So, here is the assignment:
1.Add a new function insertN(struct list *x, int num, int pos, int n) that will insert n copies of the integer num at position pos, if that is possible (if pos is too big, take appropriate action).
The main thing I'm confused by here is what he means by the position pos.
Here's the code I am working with-which was written by my teacher and I have to modify it.
#include<stdio.h>
#include<stdlib.h>
struct list {
int data;
struct list * next;
};
struct list *slist;
/*adds a node at the end of the linked list*/
void insert(struct list *x,int num){
/*if the list is empty*/
if(x==NULL){
/*create first node*/
slist=malloc(sizeof(struct list));
slist->data=num;
slist->next=NULL;
}
else{
/*go to the last node*/
while(x->next!=NULL) x=x->next;
/*add node at the end*/
x->next=malloc(sizeof(struct list));
x->next->data=num;
x->next->next=NULL;
}
}
void display(struct list *x){
/*traverse the entire linked list*/
while(x!=NULL){
printf("%d->",x->data);
x=x->next;
}
printf("NULL");
}
void reverse(struct list *x){
struct list *prev,*rev,*temp;
prev=x;
rev=NULL;
while(prev!=NULL){
temp=rev;
rev=prev;
prev=prev->next;
rev->next=temp;
}
slist=rev;
}
void search(struct list *x,int a){
struct list *runner;
int found=0;
for(runner=x;runner!=NULL;runner=runner->next){
if(runner->data==a){
printf("data found");
found=1;
break;
}
}
if(found==0) printf("data not found");
}
main(){
int number,a;
slist=NULL;/*empty linked list*/
printf("Enter the element for data part:");
scanf("%d",&number);
insert(slist,10);
insert(slist,number);
insert(slist,20);
display(slist);
printf("\n");
reverse(slist);
display(slist);
printf("\nEnter the element for searching:");
scanf("%d",&a);
search(slist,a);
printf("\n");
getchar();
getchar();
}
Again, I don't expect an answer to the problem, just an explanation and a push in the right direction.

By saying "at position 5" he means that he wants you to iterate through ("go through") the list 5-steps, then insert there.
If you have a reference to a list like so:
struct list * current;
A single step can be done like this:
current = current -> next;
Now what you have to do is do that until you are at the right position, then insert there.

So let's say slist has 3 elements in it like this:
+---+ +----+ +---+
| 7 | -> | 48 | -> | 9 | -> NULL
+---+ +----+ +---+
Which you created by doing something like:
slist=NULL;
insert(slist, 7);
insert(slist, 48);
insert(slist, 9);
Your job is to implement a function called insertN(struct list *x, int num, int pos, int n) which inserts one or more repeated elements into the list at the given position.
When I use that function I might say:
insertN(slist, 69, 1, 2);
which means "insert 2 elements containing 69 into slist at position 1".
So after the call slist should look like this:
+---+ +----+ +----+ +----+ +---+
| 7 | -> | 69 | -> | 69 | -> | 48 | -> | 9 | -> NULL
+---+ +----+ +----+ +----+ +---+

A position i can be found by following i next pointers. So 0 is the start of the list, since you get there without following a next pointer. If the list contains n elements, then position n refers to the end.
You'll have to modify the loop following the go to the last node comment. You'll also have to handle a few corner cases, 0 being one of them. (Hint: it's very similar to the case where the list is empty.)

Guys already an answer has been accepted but what must be done when pos is large.As it would be computationally very expensive. I think it would be preferably better to keep two pointers one to the begining of the list and one at the end.
But since it is singly list we can't travers it backwards.So guys what we must do for the case when pos is large Which is an important aspect of the problem which eveyone has missed.

some thing like this (this insert only one node,extend it to insert n items):
function insertN(struct list *x, int num, int pos, int n){
int k=0;
struct list *nd=x,*tmp;
while(nd){
if(k==pos){ // position reached ?
tmp=nd->next;
nd->next= new_node(num);
nd->next->next=tmp;
return 1; // succedd node inserted
}
nd=nd->next; //next node
k++; // next position
}
// nd == null means pos is too large
return 0; // failed to insert node at position pos;
}

Related

node pointer of a list wont update

I had a problem and I cannot seem to find a solution.I tried to do a simple program that creates a list and prints it in C, but when i tried to run it it looped printing the first value of the list.This is the program if anyone could help plz:
I tried adding parenthesis etc but didn't work.
#include <stdio.h>
#include <stdlib.h>
typedef struct nodo{
int dato;
struct nodo *next;
}nodo_t;
typedef nodo_t *Ptr_nodo;
int main(){
Ptr_nodo testa,temp;
int q;
temp=NULL;
testa=NULL;
temp=malloc(sizeof(nodo_t));
if(temp){
q=0;
while(q!=-1){
printf("Inserire valore: ");
scanf("%d",&q);
if(q!=-1){
temp->dato=q;
temp->next=testa;
testa=temp;
}
}
while(testa!=NULL){
printf("%d",testa->dato);
if(testa->next!=NULL)
printf(" -> ");
else
printf(" -|");
testa=testa->next;
}
}
else
printf("Errore allocazione memoria"),
free(temp);
return 0;
}
I tried out your code and got the repeated printing of the one node which was pointing to itself. What appeared to be missing was when more data was being entered, new nodes needed to be created with memory allocated for each node. With that in mind, following is a refactored version of your code.
#include <stdio.h>
#include <stdlib.h>
typedef struct nodo{
int dato;
struct nodo *next;
}nodo_t;
typedef nodo_t *Ptr_nodo;
int main(){
Ptr_nodo testa,temp;
int q;
temp=NULL;
testa=NULL;
temp=malloc(sizeof(nodo_t));
testa = temp;
if(temp){
q=0;
while(q!=-1){
printf("Insert Value: ");
scanf("%d",&q);
if(q!=-1){
temp->dato=q;
temp->next=malloc(sizeof(nodo_t)); /* Created new node and allocate memory */
temp=temp->next;
temp->next = NULL; /* Make sure this latest node has the NULL terminator */
}
}
while(testa!=NULL){
printf("%d",testa->dato);
if(testa->next!=NULL)
printf(" -> ");
else
printf(" -|");
testa=testa->next;
}
printf("\n"); /* Just added this for appearances on the terminal output */
}
else
printf("Memory allocation error"),
free(temp);
return 0;
}
Some bits to point out.
When another value is received from the user, a new node needs to be created with memory allocated via the "malloc" function.
Pointer references for the previous node and new node need to be updated once the new node is created.
In the new node, its "next" pointer needs to be set to NULL so as to ensure that the subsequent list printing does not get caught up in an endless loop.
With those bits added, following was a sample output at the terminal.
#Vera:~/C_Programs/Console/MultiNode/bin/Release$ ./MultiNode
Insert Value: 4
Insert Value: 1998
Insert Value: 22
Insert Value: 45
Insert Value: 88
Insert Value: -1
4 -> 1998 -> 22 -> 45 -> 88 -> 0 -|
One small side effect I saw was that the final node has a value of zero. I don't know if that is a desired outcome, but I will leave that as something to possibly be refined.
Give that a try and see if it meets the spirit of your project.
draw it out:
temp = malloc(...); // creates a node
+------------+
temp --> | data: ?? |
| next | --> ?? points nowhere right now
+------------+
testa --> NULL
You scanf your data, just call it 5
scanf("%d",&q); // user inputs 5
if(q!=-1){
// set data
temp->dato=q;
temp->next=testa;
+------------+
temp --> | data: 5 |
| next | --> testa, which is NULL right now
+------------+
testa=temp; // results in testa and temp pointing to the same node
+------------+
temp --> | data: 5 |
testa --> | next | --> NULL
+------------+
}
Now you loop back around
scanf("%d",&q); // user inputs 8
if(q!=-1){
// whoops, didn't create a new node, so it's still the same temp from before
temp->dato=q;
temp->next=testa;
testa=temp;
+------------+
temp --> | data: 8 |
testa --> | next | --> testa, which is the same as temp -----+
+------------+ |
^ |
| |
+-------------------------------------------------+
You have one node that points to itself. You need to create a new node on each user entry, I trust the other answer(s) show you how to do that.
You allocated only one node within the program
temp=malloc(sizeof(nodo_t));
if(temp){
//...
Then within the following while loop
while(q!=-1){
printf("Inserire valore: ");
scanf("%d",&q);
if(q!=-1){
temp->dato=q;
temp->next=testa;
testa=temp;
}
}
You are changing the data member dato of the same node because the pointer temp always points to the early allocated single node before the while loop and neither new nodes are being allocated
Its data member next points to the node itself except the first iteration of the loop when the data member next is set to the value of the pointer testa that initially was set to NULL.
So you are outputting the same node that stores the last entered value in its data member dato.
Also if the user at once will enter the value -1 then you will have uninitialized node that results in undefined behavior in the loop where the list is outputted.
You need to allocate new nodes using malloc that will store subsequent entered values. And at the end of the program you should free all the allocated nodes.
Your program can look for example the following way.
#include <stdio.h>
#include <stdlib.h>
typedef struct nodo{
int dato;
struct nodo *next;
}nodo_t;
typedef nodo_t * Ptr_nodo;
int main( void )
{
Ptr_nodo testa = NULL
while ( 1 )
{
Ptr_nodo temp = NULL;
int valore;
printf( "Inserire valore in lista (-1 - esci): " );
if ( scanf( "%d", &valore ) != 1 || valore == -1 || ( temp = malloc( sizeof( *temp ) ) ) == NULL )
{
break;
}
temp->dato = valore;
temp->next = testa;
testa = temp;
}
for ( Ptr_nodo temp = testa; temp != NULL; temp = temp->next )
{
printf( "%d -> ", temp->dato );
}
puts ( "null" );
while ( testa )
{
Ptr_nodo temp = testa;
testa = testa->next;
free( temp );
}
}

Why is my list->next pointer affected by free()?

I'm trying to implement a linked list and adding nodes to it. I encountered the following problem, when I try to free the pointer n after setting list->next to point to the same address of n, the int value inside the second node also changes to garbage value when I print it again. I want to know if inside the memory, n and list->next is stored as two separate pointers that hold the same value or it is stored as a single pointer? And if they were distinct, then why freeing n also affect list->next? Furthermore if freeing n make the second node became lost, then why I can still use the list->next->next pointer to add a third node, was list->next->next pointer also some random value that points to a random usable location ? Here is my code, sorry if my question is too vague, I'm trying my best to understand all this pointers.
#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
typedef struct node {
int number;
struct node *next;
} node;
int main(void) {
node a;
a.number = 1;
a.next = NULL;
node *list = NULL;
list = &a; // the first node
printf("%i \n", a.number);
node *n = malloc(sizeof(node)); // creating pointer to the second node
if (n != NULL) {
n->number = 2;
n->next = NULL;
}
list->next = n; // add the node to the list
printf("%p \n%p \n", n, list->next); // print out the address and value
printf("%i \n", list->next->number);
free(n);
printf("%p \n%p \n", n, list->next); // print out the address and value
printf("%i \n", list->next->number);
n = malloc(sizeof(node));
printf("%p \n%p \n", n, list->next);
if (n != NULL) {
n->number = 3;
n->next = NULL;
}
list->next->next = n;
printf("%i\n", (*(*(*list).next).next).number);
return 0;
}
Here is the output
1
0x5562319d62a0
0x5562319d62a0
2
0x5562319d62a0
0x5562319d62a0
1445140950
0x5562319d62a0
0x5562319d62a0
3
The assignment
list->next = n
doesn't copy the allocated memory. It just add another pointer pointing to the same memory.
If we "draw" it, before the assignment it looks something like this:
+---+ +-----------------+
| n | ---> | memory for node |
+---+ +-----------------+
Then after the assignment you have:
+---+
| n | -----------\
+---+ | +-----------------+
>--> | memory for node |
+------------+ | +-----------------+
| list->next | --/
+------------+
Then you pass n to free leading to this situation:
+---+
| n | -----------\
+---+ |
>--> ???
+------------+ |
| list->next | --/
+------------+
After the call to free, the pointer list->next is invalid. Any attempt to dereference it will lead to undefined behavior.

I created a push and pop function in C but do not know how to print them in order

I've recently studied about linked-list and tried to create a push and pop function.
I've successfully created one which look like this.
#include <stdio.h>
#include <stdlib.h>
struct node{
int data;
struct node *next;
};
struct node* buffer = NULL;
void push(int elem){
struct node *new_element = (struct node*)malloc(sizeof(struct node));
new_element->next = buffer;
new_element->data = elem;
buffer = new_element;
}
int pop(void){
int elem = buffer->data;
struct node *eliminate = buffer;
buffer = eliminate->next;
free(eliminate);
return elem;
}
Afterwards I tried to print them this way:
int main(void) {
push(5);
push(7);
push(8);
pop();
printf("%d %d", buffer->data, buffer->next->data);
}
However, the result was 7 5 instead of 5 7. Is there anything wrong with my push function?
After you do:
push(5);
push(7);
push(8);
You have the following linked list:
5 <- 7 <- 8 <- buffer
After the pop you have: 5 <- 7 <- buffer
That is why buffer->data is 7 and buffer->next->data is 5.
In order to print the list in the correct order you will need an pointer pointing to the first node. In your case the 5. Also with your approach you should make it a double linked list.
struct node{
int data;
struct node *next;
};
struct node* start = NULL;
struct node* buffer = NULL;
void push(int elem){
struct node *new_element = (struct node*)malloc(sizeof(struct node));
new_element->next = buffer;
new_element->data = elem;
if (buffer == NULL) start = new_element; // this is the magic
buffer = new_element;
}
Actually, the code is running correctly, this is what your code is doing:
buff=NULL
after push(5): buff=5->NULL
after push(7): buff=7->5->NULL
after push(8): buff=8->7->5->NULL
after pop(): buff=7->5->NULL
thus buffer->data is 7
and buffer->next->data is 5
You should expect 7, 5 as the output. You implemented a Last In First Out stack. This means that the node with data = 8 is the last node pushed onto the stack and the first one out. When you pop that node you are left with 7 and 5 and 7 is on top of the stack.
Here's a link to a good tutorial about stacks
What you experience is the correct behavior. In fact your push() / pop() couple implements a LIFO behavior: Last In, First Out (push() and pop() are actually the common interface name of the functions interacting with the stack abstract data type). The order you expect, instead, would have been shown in case of a FIFO implementation (First In, First Out).
Here is the content of your stack step by step:
push(5);: only an element is present
-----
| 5 |
-----
^
|
buffer
push(7);:
---------
| 7 | 5 |
---------
^
|
buffer
push(8);:
-------------
| 8 | 7 | 5 |
-------------
^
|
buffer
pop();: the last inserted element (8, last in) is removed (first out)
---------
| 7 | 5 |
---------
^
|
buffer
And this is actually what is printed.
Due to the LIFO nature of push 5 - push 7 -push 8 - pop, when 8 is popped (removed from list) only 5 & 7 remain, and these two will appear in reverse of the order in which they were entered.
Furthermore, If you prefer a sorted list of nodes, read on.
"However, the result was "7 5" instead of "5 7". Is there anything wrong with my push function? "
Because the steps do not necessarily have content enter in desired order, you should consider using a sort function in conjunction with printing. Step to a merge sort follow:
MergeSort(headRef)
If the head is NULL or there is only one element in the Linked List
then return.
Else divide the linked list into two halves.
FrontBackSplit(head, &a, &b); /* a and b are two halves */
Sort the two halves a and b.
MergeSort(a);
MergeSort(b);
Merge the sorted a and b (using SortedMerge() discussed here) and update the head pointer using headRef.
*headRef = SortedMerge(a, b);
Excerpt code showing sample implementation from here (see link for full example)
/* Driver program to test above functions*/
int main()
{
/* Start with the empty list */
struct Node* res = NULL;
struct Node* a = NULL;
/* Let us create a unsorted linked lists to test the functions
Created lists shall be a: 2->3->20->5->10->15 */
push(&a, 15);
push(&a, 10);
push(&a, 5);
push(&a, 20);
push(&a, 3);
push(&a, 2);
/* Sort the above created Linked List */
MergeSort(&a);
printf("Sorted Linked List is: \n");
printList(a);
getchar();
return 0;
}
... several other supporting functions
// C code for linked list merged sort
#include <stdio.h>
#include <stdlib.h>
/* Link list node */
struct Node {
int data;
struct Node* next;
};
/* function prototypes */
struct Node* SortedMerge(struct Node* a, struct Node* b);
void FrontBackSplit(struct Node* source,
struct Node** frontRef, struct Node** backRef);
/* sorts the linked list by changing next pointers (not data) */
void MergeSort(struct Node** headRef)
{
struct Node* head = *headRef;
struct Node* a;
struct Node* b;
/* Base case -- length 0 or 1 */
if ((head == NULL) || (head->next == NULL)) {
return;
}
/* Split head into 'a' and 'b' sublists */
FrontBackSplit(head, &a, &b);
/* Recursively sort the sublists */
MergeSort(&a);
MergeSort(&b);
/* answer = merge the two sorted lists together */
*headRef = SortedMerge(a, b);
}

Insertion Sort for Singly Linked List in C

I'm trying to improve my knowledge on Algorithms and Data Structures, so for the last 5-6 days I've been trying to implement different algorithms on different data structures. I've the basic knowledge on singly,doubly, and circular linked lists, and I can implement an insertion sort algorithm with arrays.
However, implementing an insertion sort algorithm with a singly linked list turned out be much more problematic than I initally was expecting. I do not like looking at other people's code and copying them to understand a concept. I really like to try to do it myself first. So, I've written some lines:
#include <stdio.h>
#include <stdlib.h>
typedef struct Node node;
struct Node{
int num;
node *next;
};
void printLinkedList(node *ptr);
void insertionSortLinkedList(node *p,node *head,int sizeOfList);
/* Driver program applying Insertion Sort to a Singly Linked List */
int main(int argc,char *argv[]){
int i, sizeOfList=argc-1;
node *head,*ptr;
ptr=(node*)malloc(sizeOfList*sizeof(node));
for(i=0;i<sizeOfList;i++){
(ptr+i)->num=atoi(argv[i+1]);
(ptr+i)->next=(ptr+i+1);
}
(ptr + sizeOfList-1)->next=NULL;
head=ptr;
printLinkedList(head);
insertionSortLinkedList(ptr,head,sizeOfList);
return 0;
}
void printLinkedList(node *ptr) {
while (ptr != NULL) {
printf("%d ", ptr->num);
ptr=ptr->next;
}
printf("\n\n");
}
void insertionSortLinkedList(node *p,node *head,int sizeOfList){
int i=0;
int N=1;
int flag;
node *temp;
while(N<sizeOfList){
flag=0;
/* node N > node i */
if((p+N)->num>(p+i)->num){
i++;
}
/* node i >= node N */
else{
/* node i = node N */
if((p+N)->num==(p+i)->num){ // FIRST ERROR HERE. DOES NOT ENTER HERE FOR 2 1 3 1 5 4 3 WHEN 1(i) 2 3 1(N) 5 4 3
/* i = N */
if(i==N){
flag=1;
}
/* i != N */
else{
temp=(p+N);
(p+N-1)->next=(p+N)->next;
temp->next=(p+i)->next;
(p+i)->next=temp;
flag=1;
}
}
/* node i > node N */
else{
/* i = 0 and Head needs to change */
if(i==0){
temp=(p+N);
(p+N-1)->next=(p+N)->next;
temp->next=(p+i);
head=temp;
flag=1;
}
/* i != 0 and Head needs to change */
else{
temp=(p+N);
(p+N-1)->next=(p+N)->next;
temp->next=(p+i);
(p+i-1)->next=temp;
flag=1;
}
}
}
/* Increase N and set i equal zero */
if(flag==1){
i=0;
N++;
}
}
printf("Our ordered values in the LinkedList: ");
printLinkedList(head);
}
My code seems to be working fine up to a specific point. For example if I enter to terminal:
./a.out 2 1 3 1 5 4 3
The first "pivot" works fine and algorithm swaps the "2" and "1". Thus we get:
1 2 3 1 5 4 3
Then the next pivot also works fine and algorithm compares first "1" and "3", then "2" and "3" and it decides to do nothing, just incrementing the "pivot". So we get:
1 2 3 1 5 4 3
At this point my algorithm goes crazy and it compares "1" and "1" decides that "1(of first node)" is greater than "1(of pivot)". The rest of the algorithm does not work. And as the final result, the so called "sorted" array printed out is:
1 4
I've seen on the other websites problems related to insertion sort with linked lists, however they follow a different approach then what my code tries to do. If possible, I just would like to solve the bug behind this algorithm. If not, then I would probably give up and implement the code like the others. I would much appreciate if anyone could direct me in the correct mindset to solve this problem or tell me why this code is not working probably. Also if something about this, is fundamentally wrong, please do tell me...
The main problem of your algorithm is that you treat the linked list structure as an array and try to perform the operations like p+N and so on... Actually a linked list is not an array so the pointers to the nodes are not placed sequentially in the memory but they are scattered around an address space and operations p+N not always points to the next node. So to iterate over the list you must only use p->next statement.
Thanks to #Mykola 's directions I was able to implement the insertion sort in linked lists correctly. I've realized that one of my biggest problems was not handling the pointers of my nodes carefully. Passing their reference instead, was a big help. Also I've realized I was not traversing the linked list correctly. Due to these correction I had to change my code a little bit. Also I've tried to make my code clearer and I've added a push() function.
I'm going to include my code below, so that if anyone finds themselves in a situation similar to mine, they can check it as a reference:
#include <stdio.h>
#include <stdlib.h>
typedef struct Node node;
struct Node{
int data;
node* next;
};
void printList(node* head);
void push(node** head_ref,int data);
void insertionSort(node** head_ref);
void insertIntoSorted(node** sorted_ref,node* new_node);
/* Driver program that applies insertion sort to singly linked lists */
int main(int argc, char* argv[]){
int i, sizeOfList;
sizeOfList=argc-1;
node *head;
head=NULL;
for(i=sizeOfList;i>0;i--){
push(&head,atoi(argv[i]));
}
/* Print the linked list before the insertion sort */
printf("Your list before the insertion sort is: ");
printList(head);
/* insertion sort function */
insertionSort(&head);
/* Print the linked list after the insertion sort */
printf("Your list after the sort is: ");
printList(head);
return EXIT_SUCCESS;
}
/* Utility function that inserts a new node at the beginning of a linked list */
void push(node** head_ref,int data){
//allocate node and fill
node* new_node;
new_node=(node*)malloc(sizeof(node));
new_node->data=data;
//link
new_node->next=*head_ref;
*head_ref=new_node;
}
/* Utility function to print a linked list */
void printList(node* head){
node* temp;
temp=head;
while(temp!=NULL){
printf("%d ",temp->data);
temp=temp->next;
}
printf("\n");
}
/* Function to sort a singly linked list using insertion sort */
void insertionSort(node** head_ref){
/* Initialize the sorted linked list */
node* sorted;
sorted=NULL;
/* Traverse the given linked list and insert every node to "sorted" */
node* current;
current=*head_ref;
while(current!=NULL){
/* Store "next" for next iteration */
node* next;
next=current->next;
/*Insert "current" into the "sorted" linked list */
insertIntoSorted(&sorted, current);
/* Update "current" to the next node */
current=next;
}
*head_ref=sorted;
}
/* Function to insert a given node in the "sorted" linked list. Where
* the insertion sort actually occurs.
*/
void insertIntoSorted(node** sorted_ref,node* new_node){
node* current;
/* Special case for the head end of the "sorted" */
if ((*sorted_ref == NULL) || ((*sorted_ref)->data >= new_node->data))
{
new_node->next = *sorted_ref;
*sorted_ref = new_node;
}
/* Locate the node before the point of insertion */
else
{
current = *sorted_ref;
while ((current->next!=NULL) && (current->next->data < new_node->data)){
current = current->next;
}
new_node->next = current->next;
current->next = new_node;
}
}

Swap nodes in a singly-linked list

I am trying to swap two nodes. For example if the nodes are a and b I am passing the pointers
(a-1)->next and (b-1)->next which are basically nodes a and b.
void swap(struct stack **a,struct stack **b)
{
struct stack *temp1 = *a, *temp2 = *b, *temp3 = *b;
*a = *b;
(*b)->next = (temp1)->next;
temp2 = temp1;
(temp2)->next = temp3->next;
}
What am I doing wrong? When I am trying to print the nodes after calling the function it's an infinite loop. Please help.
Why Infinite loop?
Infinite loop is because of self loop in your list after calling swap() function. In swap() code following statement is buggy.
(*b)->next = (temp1)->next;
Why?: Because after the assignment statement in swap() function temp1's next starts pointing to b node. And node[b]'s next point to itself in a loop. And the self loop is reason for infinite loop, somewhere in your code where you traverse linked list.
Below I drawn to show how swap() works step-by-step. May be this help you to understand your error:
You didn't mention but I am assuming linked list having following relation between a and b: (read red comments)
(step-1):
+----+----+----+ +---+----+----+
| one |----->| two |
+----+----+----+ +---+---+-----+
^ ^ ^ ^
| | | |
| *a | *b
| |
temp1 temp2, temp3 "after assignment to temp variables"
(step-2): ^
|
*a = *b | *a "<--- next step"
(step-3): The buggy statement
(*b)->next = (temp1)->next; "Change link: (temp1)->next; is `two` node"
" *b is `two`, So Self loop"
+----+----+----+ +---+----+----+ <---|
| one | | two |-----|
+----+----+----+ +---+---+-----+
^ ^ ^ ^
| | | |
| | *b *a
| |
temp1 temp2, temp3 " after assignment to temp"
See (temp1)->next; is actually b and you are assigning (*b)->next = (*b) by doing (*b)->next = (temp1)->next; hence adding a self loop.
(step-4):
I think with the diagram you can easily understand what last two lines of your swap() code are doing:
temp2 = temp1;
(temp2)->next = temp3->next;
Following is my diagram for this two lines:
temp2 = temp1;
+----+----+----+ +---+----+----+ <---|
| one | | two |-----| "<--- Self loop"
+----+----+----+ +---+---+-----+
^ ^ ^ ^
| | | |
| | *b *a
| |
temp2 = temp1; temp3
(step-5): Even last line of your function swap() left loop as below:
(temp2)->next = temp3->next; " last line of your code"
+----+----+----+ +---+----+----+ <---|
| one |----->| two |-----| "<-- Self loop"
+----+----+----+ +---+---+-----+
^ ^ ^ ^
| | | |
| | *b *a
| |
temp2 = temp1; temp3
So loop still there at two node so infinite loop.
How to swap two nodes in single linked list?
One way is swap node's data instead of swapping node's position it self in linked list (as I commented to your question). But you wants to swap node's position in list.
Well this good! if node data size is larger, that time its better to swap node's position rather then swap node's data(swapping data will be bad choice)
Because you having single linked list, to swap any two arbitrary nodes in list you need there previous node addresses too. (this is the point you don't consider in your swapping logic)
WHY need previous pointers?:
Suppose after some successful insert(push) operations, your list becomes as follows:
0 <--------TOP - "head"
9 <--p
2
6 <--q
5
A horizontal diagram- Suppose you want to swap say two nodes (q) and (p):
+---+ +---+ +---+ +---+ +---+
| 0 |--->| 9 |--->| 2 |--->| 6 |--->| 5 |---
+---+ +---+ +---+ +---+ +---+ |
^ ^ ^ null
| | |
| (q) (p)
(head)
As I said, to swap we need previous pointers. You need to think about following
(In theory, I am writing for specific nodes (p) and (q) just to keep explanation simple. but my implementation is quit general):
In list previous pointers:
node[0] points to node[9] that is (q), and
node[2] points to node[6] that is (p)
And
node[9] points to node[2]
node[6] points to node[5]
NOTICE: If you want to swap two nodes say node[ 9 ] and node[ 6 ] then you should use pointers of the nodes previous to these two nodes.
For example: two swap node[ 9 ] and [ 6 ], you also need to change next pointer of node[ 0 ] and next pointer of node[ 2 ] in above diagram.
How would be the list after swapping this two nodes?
+---+ +---+ +---+ +---+ +---+
| 0 |--->| 6 |--->| 2 |--->| 9 |--->| 5 |---
+---+ +---+ +---+ +---+ +---+ |
^ ^ ^ null
| | |
| (p) (q)
(head)
What is now in previous nodes [o] and [2]?
After swapping, In list previous pointers
node[0] points to node[6] that is (q), and
node[2] points to node[9] that is (p)
And
node[9] points to node[5]
node[6] points to node[2]
So if you want to swap two nodes; there immediate previous node also effects and because list is single link list you need previous pointers too.
How to find previous node pointers?
Suppose you want to swap any two nodes node[p] and node[q] then you can use head pointer to find previous node.
So swap function syntax (In my implementation) is like:
void swap(struct stack **head, // head node
struct stack **a, // first candidate node to swap
struct stack **b); // first candidate node to swap
And you will call function like:
swap(&head, &p, &q);
Definition: (To understand code please read comments I added at almost each line)
void swap(struct stack **head,
struct stack **a,
struct stack **b){
// first check if a agrgument is null
if( (*head) == NULL || // Empty list
(*a) == NULL || (*b) == NULL){ // one node is null
// Nothing to swap, just return
printf("\n Nothing to swap, just return \n");
return;
}
// find previos nodes
struct stack* pre_a = get_prevnd(*head, *a);
struct stack* pre_b = get_prevnd(*head, *b);
//Now swap previous node's next
if(pre_a) pre_a->next = (*b); // a's previous become b's previous, and
if(pre_b) pre_b->next = (*a); // b's previous become a's previous
//Now swap next fiels of candidate nodes
struct stack* temp = NULL;
temp = (*a)->next;
(*a)->next = (*b)->next;
(*b)->next = temp;
//change head: if any node was a head
if((*head)==(*a))
*head = *b;
else
if((*head)==(*b))
*head = *a;
}
In swap() function you can notice that I call a helper function get_prevnd(, );. This function returns address of previous node in list. In The function get_prevnd(, );, first argument is list head and second argument is node for which you are looking for.
// find previous node function()
struct stack* get_prevnd(
struct stack* head,
struct stack* a
){
if(head == a){
// node[a] is first node
return NULL;
}
struct stack* temp = head; // temp is current node
struct stack* pre_a = NULL;
while(temp && temp!=a){ //search while not reach to end or the node
pre_a = temp; // find previous node
temp = temp->next;
}
if(temp!=a){// node[a] not present in list
fprintf(stderr, "\n error: node not found!\n");
exit(EXIT_FAILURE); // bad technique to exit()
}
return pre_a;
}
And fortunately the code is WORKING :). Below is link for online test of this code. I have tested for various kind of inputs.
CodePad: To Swap node in single linked list. Please check output.
And sorry for bad English
I was hoping for cut-and-paste code, but didn't find it. If anyone is still interested, this is the answer. I did the brute force analysis of all 3 cases.
// swaps nodes at locations *sp and *tp
struct stack *s = *sp; // store locations to prevent overwritten bugs
struct stack *t = *tp;
if(&t->next == sp) { // order u (tp)-> t (sp)-> s -> ...
t->next = s->next;
s->next = t;
*tp = s;
} else if(&s->next == tp) { // order u (sp)-> s (tp)-> t -> ...
s->next = t->next;
t->next = s;
*sp = t;
} else { // disconnected u (sp)->s -> ..., v (tp)->t -> ...
struct stack *next = s->next;
s->next = t->next;
t->next = next;
*sp = t;
*tp = s;
}
// If you track the end of your list, it be the one pointing to NULL.
if(s->next == NULL) {
end = &s->next;
} else if(t->next == NULL) {
end = &t->next;
}
Note: This code works if sp == tp, but assumes you don't have the pathological case where BOTH &s->next == tp && &t->next == sp (starting with cycle).
"KING KHAN"
SwapanyTwoNodeData(int, int); this function take two integer as parameter and swap these
node data.
1->2->6->3->4->5
SwapanyTwoNodeData (2,4);
1->3->6->2->4->5
100% Working Function. . . . Enjoy.
void Swap_Any_Two_Locations_data(int x,int x1){
if(head!=NULL){
int count=1,count1=1;
Node *temp,*temp1;
temp=head;
temp1=head;
while(temp->next!=NULL && count!=x ){
temp=temp->next;
count++;
}
while(temp1->next!=NULL && count1!=x1){
temp1=temp1->next;
count1++;
}
if(count==x && count1==x1){
int z=0;
z=temp->info;
temp->info=temp1->info;
temp1->info=z;
cout<<"Data Swapped"<<endl;
}
}
}

Resources