Swap nodes in a singly-linked list - c

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;
}
}
}

Related

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.

How to delete a node in a linked list in c [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
what i need to do is to implement a function in c for deleting a node in a linked list, using a for and while loop with strcmp. The program compiles fine but the loop never stop, any suggestion on how to make it better?
The structure is this:
struct Test
{
char name[16];
int id;
};
typedef struct Node
{
struct Test structure;
struct Node * next;
}TNode;
typedef TNode * Nodo;
And the function i wrote is this:
void Delete(Nodo * pp)
{
Nodo i;
char temp[16], name[16];
printf("Insert the name to delete:");
scanf(" %s", name);
for(i = *pp; i->next != NULL ; i = i->next)
{
if(strcmp(i->structure.name, name) == 0)
{
while(i->next != NULL)
{
strcpy(temp,i->structure.name);
strcpy(i->structure.name, i->next->structure.name);
strcpy(i->next->structure.name, temp);
i = i->next;
}
}
}
}
UPDATE: The working function is this, thanks to Some programmer dude for the explanation:
void Delete(Nodo * pp)
{
Nodo i, prev;
char name[16];
printf("Insert the name to delete:");
scanf(" %s", name);
//case for the first node
if(strcmp((*pp)->structure.name, name) == 0)
{
Nodo old = *pp;
*pp = (*pp)->next;
free(old);
return;
}
//loop to delete node inside list
for(prev = *pp, i = prev->next; i != NULL ; prev = i, i = i->next)
{
if(strcmp(i->structure.name, name) == 0)
{
prev->next = i->next;
free(i);
break;
}
}
}
[Note: This doesn't actually answer the question, but it tells how to unlink nodes in a single-linked list, which IMO is the bigger problem the OP have.]
Lets say you have the following list
+---+ +---+ +---+ +---+
| A | -> | B | -> | c | -> | D |
+---+ +---+ +---+ +---+
If you want to remove node B then you don't copy the contents of the remaining list. Because that would give you the follow list:
+---+ +---+ +---+ +---+
| A | -> | C | -> | D | -> | D |
+---+ +---+ +---+ +---+
And that's not correct.
Instead you make the A node's next pointer point to C instead, so now the list becomes
+---+ +---+ +---+ +---+
| A | -\ | B | /-> | c | -> | D |
+---+ | +---+ | +---+ +---+
\-------/
Then you just free the node B, and you end up with
+---+ +---+ +---+
| A | -> | c | -> | D |
+---+ +---+ +---+
The trick to unlinking the node is to keep track of the previous node. It could be implemented something like this:
// Special case: Removing the first node in the list
if (strcmp((*pp)->structure.name, name) == 0)
{
TNode *old = *pp; // Save a pointer to the node that should be removed
*pp = (*pp)->next; // Actually unlink the node from the list
free(old); // Free the memory of the old node
return;
}
TNode *prev; // To keep track of previous node
TNode *curr; // The "current" node
for (prev = *pp, curr = prev->next; curr != NULL; prev = curr, curr = curr->next)
{
if (strcmp(curr->structure.name, name) == 0)
{
// Found the node to remove
prev->next = curr->next; // Unlink the current node from the list
free(curr); // Free the node
break; // No need to iterate anymore
}
}
The "special case" of the first node being removed could also be solved inside the loop, by initializing prev to NULL, and start curr with *pp instead. Then you need to check if prev is NULL or not inside the if in the loop.
The code might look like more, and it might be more lines (even after removing some or all of the empty lines), but I think most people would say it's easier to follow and see what's going on.
Of course, you also need to add a check for an empty list and that pp itself is not null (like pp != NULL && *pp != NULL).

Storing an array of structs in a linked list

I have an array of struts called arrayOfElements , each element being a struct called Element
typedef struct {
void* data;
} Element;
data is a void pointer as I dont know in advanced what type of variable will be stored
I've malloc'd this array to have 4 elements ( this is done by user input but ive hard coded 4 for this question)
Element* arrayOfElements;
arrayOfElements= malloc(4 * sizeof(Element));
Now to this point I can store strings and ints in arrayOfElements
Store Int
arrayOfElements[0].data = malloc( sizeof(int) );
int *ptr = arrayOfElements[0].data;
*ptr = 65;
Store String
arrayOfElements[0].data = malloc( strlen(str) + 1 );
strcpy( arrayOfElements[0].data, str );
And that all works. My Issue is how do I got about making a linked List and making each element store an instance of arrayOfElements
so far my linked list is
typedef struct LinkedListNode {
void** ElementArray;
struct LinkedListNode* next;
} LinkedListNode;
typedef struct {
LinkedListNode* head;
} LinkedList;
so the void** ElementArray will point to each arrayOfElements
void insert(LinkedList* head, Element inArrayOfElements)
{
LinkedListNode insertNode;
/* Points ElementArray to inArrayOfElements */
HOW DO I DO THIS AS ElementArray is a void**
/* Points next to the head */
(*insertNode).next = head;
/* Re-points head to new head of Linked List */
head = insertNode;
}
My Goal is to have something like this
LINKEDLIST
+---+ +---+---+----+
| | -> | | | | arrayofElements
+---+ +---+---+----+ +---+---+----+
| | -------------------> | | | |
+---+ +---+---+----+ +---+---+----+
| | -> | | | |
+---+ +---+---+----+ +---+---+----+
| | -------------------> | | | |
+---+ +---+---+----+
Question / TL;DR
My question is how do I make void** ElementArray (in the linked list) point to arrayOfElements.
If I understand your question correct, there is no need for double pointers. Just do:
typedef struct LinkedListNode {
Element* data;
struct LinkedListNode* next;
} LinkedListNode;
LinkedListNode* insert(LinkedListNode* head, Element* inArrayOfElements)
{
LinkedListNode* insertNode = malloc(sizeof(LinkedListNode));
insertNode->next = head;
insertNode->data = inArrayOfElements;
return insertNode;
}
Use it like:
head = insert(head, someArrayOfElements);
Note: The real code should check for NULL pointers but I omitted that for simplicity.

How does head connected to tail when deleting the list

I have a function which creates a list based on a given array,
this is the function:
typedef struct Item
{
int num;
struct Item* next;
}*PItem;
int main()
{
int Arr[N] = { 3, 4, 1, 0, 8 }, i;
PItem list = NULL, tail = NULL;
CreateListFromArray(&list, &tail, Arr);
}
void CreateListFromArray(PItem* head, PItem* tail, int *Arr)
{
int i;
PItem temp;
for (i = 0; i<N; i++)
{
temp = (PItem)malloc(sizeof(struct Item));
if (temp == NULL)
{
DeleteList(head);
Error_Msg("Memmory!");
}
temp->num = Arr[i];
temp->next = NULL;
if (*head == NULL)
*head = temp;
else
(*tail)->next = temp;
*tail = temp;
}
}
I understand that if List is empty, then head's null is initialized to the first allocated temp (arr[0]). But after that, for these arrays arr[1],..,arr[N], I update only the tail, meaning that all the tails from arr[1] to arr[N] are connected. but how does the head (arr[0]) POINTS/connected to arr[1]?
I ask this because, when I try to print the list, I use temp = head, and advance head until temp is null, but when I advance head, how does it know that it has to advance to arr[1]?
Here's the full code: http://pastebin.com/VPCfMU4X
After the first iteration of the loop, head and tail point to the same element which contains arr[0]. After the second iteration, (*tail)->next (which is the same as (*head)->next) point to the new element that contains arr[1], and tail is moved up to this value. Subsequent iterations keep appending to the end of the list.
So after one iteration, you have this:
head tail
| |
v v
---------------
| 3 | NULL |
---------------
After the second iteration, you have this:
head tail
| |
v v
--------------- ---------------
| 3 | .-----|--->| 4 | NULL |
--------------- ---------------
And the third:
head tail
| |
v v
--------------- --------------- ---------------
| 3 | .-----|--->| 4 | .-----|--->| 1 | NULL |
--------------- --------------- ---------------

More linked lists in 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;
}

Resources