简体   繁体   中英

how can i swap two nodes without exchanging data

#include <stdio.h>
#include <stdlib.h>

struct node {   
    int data;
    struct node *next;
};
struct node *head;

void createnodeatbeg(int key) {
    struct node *new = (struct node*)malloc(sizeof(struct node));
    new->data = key;
    new->next = head;
    head = new;
}

void printlist() {
    struct node *temp = head;
    printf("list is:");
    while (temp != NULL) {
        printf("%d  ", temp->data);
        temp = temp->next;
    }
    printf("\n");
}

void swapnodes(int x, int y) {
    struct node *prevX = NULL;
    struct node *prevY = NULL;
    struct node *currX = head;
    struct node *currY = head;
    while (currX->data != x && currX != NULL) {
        prevX = currX;
        currX = currX->next;
    }
    printf("not found\n");
    while (currY->data != y && currY != NULL) {
        prevY = currY;
        currY = currY->next;
    }

    if (currX == NULL || currY == NULL) {
        printf("elements not found\n");
        return;
    }
    struct node *swap = currY->next;
    prevX->next = currY;
    currY->next = prevY;
    prevY->next = currX;
    currX->next = swap;    
}

int main() {    
    head = NULL;
    int nodes, key;
    printf("enter number of nodes\n");
    scanf("%d", &nodes);
    for (int i = 0; i < nodes; i++) {
        int data;
        printf("enter number\n");
        scanf("%d", &data);
        createnodeatbeg(data);
    }
    printlist();
    int x, y;
    printf("enter the values from the list to be swapped\n");
    scanf("%d %d", &x, &y);
    swapnodes(x, y);    
    printf("swapped list is:\n");
    printlist();
}

My code works when elements (x and y) are present in the list but if it is not present in the list then error is ./a.out terminated by signal SIGSEGV (Address boundary error) . The problem is that the control doesn't comes out of the first while loop in swapNodes() function. The code takes a user input and creates a node at the beginning.

The order of operands in the conditions of the while statements is wrong.

while(currX->data!=x && currX!=NULL)
{
    prevX=currX;
    currX=currX->next;
}
//...
while(currY->data!=y && currY!=NULL)
{
    prevY=currY;
    currY=currY->next;
}

Here must be

while(currX != NULL && currX->data!=x)
{
    prevX=currX;
    currX=currX->next;
}
//...
while(currY != NULL && currY->data!=y)
{
    prevY=currY;
    currY=currY->next;
}

So if for example currX is equal to NULL then the expression currX->data!=x will not be eva;luated.

This code snippet

struct node *swap = currY->next;
prevX->next = currY;
currY->next = prevY;
prevY->next = currX;
currX->next = swap;  

is also wrong because for example prevX or prevY can be equal to NULL .

And you have to deal with the head in the function by reference. Otherwise the head node will not be changed.

You should split the function into two functions. The first one founds the node with the given value and the second one will swap found nodes if they are not equal to NULL .

Also it is a bad idea when functions depend on global variables. In fact your program can not deal with two lists simultaneously.

Here is a demonstrative program that shows how the function swap can be implemented.

#include <stdio.h>
#include <stdlib.h>

struct node 
{   
    int data;
    struct node *next;
};

struct node ** find( struct node **head, int data )
{
    while ( *head && ( *head )->data != data ) head = &( *head )->next;

    return head;
}

void swap( struct node **head, int data1, int data2 )
{
    struct node **left, **right;

    if ( *( left = find( head, data1 ) ) && *( right = find( head, data2 ) ) )
    {
        struct node *tmp = *left;
        *left = *right;
        *right = tmp;

        tmp = ( *left )->next;
        ( *left )->next = ( *right )->next;
        ( *right )->next = tmp;
    }
}

int push_front( struct node **head, int data )
{
    struct node *tmp = malloc( sizeof( struct node ) );
    int success = tmp != NULL;

    if ( success )
    {
        tmp->data = data;
        tmp->next = *head;
        *head = tmp;
    }

    return success;
}

void display( struct node **head )
{
    for ( struct node *current = *head; current; current = current->next )
    {
        printf( "%d ", current->data );
    }
}

int main(void) 
{
    const int N = 10;
    struct node *head = NULL;

    for ( int i = 0; i < N; i++ ) push_front( &head, i );

    display( &head );
    putchar( '\n' );

    for ( int i = 0; i < N; i+=2 )
    {
        swap( &head, i, i + 1 );
    }

    display( &head );
    putchar( '\n' );

    return 0;
}

Its output is

9 8 7 6 5 4 3 2 1 0 
8 9 6 7 4 5 2 3 0 1 

The problem is in following identical lines:

  • while(currX->data!=x && currX!=NULL)
  • while(currY->data!=y && currY!=NULL)

This is because instead of fist checking for NULL and then use it, you are checking for NULL latter. So when x or y is not present then you are trying to access NULL->data , which is giving Segmentation Fault Error (SIGSEGV)

Change it to following respectively:

  • while(currX!=NULL && currX->data!=x)
  • while(currY!=NULL && currY->data!=y)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM