【问题标题】:how can i swap two nodes without exchanging data如何在不交换数据的情况下交换两个节点
【发布时间】:2018-04-16 13:22:16
【问题描述】:
#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();
}

我的代码在列表中存在元素(x 和 y)时有效,但如果列表中不存在,则错误为 ./a.out terminated by signal SIGSEGV (Address boundary error)。 问题是控件没有出现在swapNodes() 函数中的第一个while 循环中。 该代码接受用户输入并在开始时创建一个节点。

【问题讨论】:

  • 除了@cse 提到的,如果交换第一个和最后一个节点,交换逻辑中也存在一个错误。做一些文书工作。

标签: c pointers linked-list swap singly-linked-list


【解决方案1】:

while语句条件中的操作数顺序错误。

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

这里一定是

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

因此,例如,如果 currX 等于 NULL,则表达式 currX-&gt;data!=x 将不会被评估。

这段代码sn-p

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

也是错误的,因为例如prevXprevY 可以等于NULL

而且你必须通过引用来处理函数中的头部。否则头节点不会改变。

您应该将函数拆分为两个函数。第一个找到具有给定值的节点,第二个将交换找到的节点,如果它们不等于NULL

当函数依赖于全局变量时也是一个坏主意。事实上你的程序不能同时处理两个列表。

这是一个演示程序,展示了如何实现函数交换。

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

它的输出是

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

【讨论】:

    【解决方案2】:

    问题在于以下相同的行:

    • while(currX-&gt;data!=x &amp;&amp; currX!=NULL)
    • while(currY-&gt;data!=y &amp;&amp; currY!=NULL)

    这是因为不是先检查NULL 然后使用它,而是检查NULL 后者。因此,当 xy 不存在时,您将尝试访问 NULL-&gt;data,这会导致 Segmentation Fault Error (SIGSEGV)

    分别改成如下:

    • while(currX!=NULL &amp;&amp; currX-&gt;data!=x)
    • while(currY!=NULL &amp;&amp; currY-&gt;data!=y)

    【讨论】:

    • cse 的解决方案有效,因为当“and”的左边部分为假(这使得“and”为假)时,右边部分不会被测试。
    • 最好也引用这个概念的名称,“短路逻辑运算符”或“短路评估”[link]en.wikipedia.org/wiki/Short-circuit_evaluation
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-04
    • 1970-01-01
    • 1970-01-01
    • 2015-05-25
    • 1970-01-01
    • 1970-01-01
    • 2021-01-14
    相关资源
    最近更新 更多