【问题标题】:Swapping nodes in linked list交换链表中的节点
【发布时间】:2017-12-07 20:20:11
【问题描述】:

我试图创建函数(swapNodes)来交换链表中的节点。 在这里,我存储了要交换的节点的前一个和下一个地址。 但是我的代码陷入了无限循环。

可以将此代码作为工作代码还是错误的方法?

#include<stdio.h>
#include<stdlib.h>
 struct Node
{
    int data;
    struct Node *next;
};
void push(struct Node** head_ref, int new_data)
{
    struct Node* new_node =
        (struct Node*) malloc(sizeof(struct Node));

    new_node->data  = new_data;
    new_node->next = (*head_ref);
    (*head_ref)    = new_node;
}


void printList(struct Node *node)
{
    while(node != NULL)
    {
        printf("%d ", node->data);
        node = node->next;
    }
}

void swapNodes(struct Node** headr,int key1,int key2)
{
    struct Node* temp1 = *headr;
    struct Node* temp2 = *headr;

    if(key1 == key2)
    return;

    struct Node* prev1 =NULL;
    struct Node* next1 =temp1;
    while(temp1->data !=key1 && next1 !=NULL)
    {
    prev1 =temp1;
    temp1 =temp1->next;
    next1 =temp1->next;
    }
    struct Node* prev2 =NULL;
    struct Node* next2 =temp2;
    while(temp2->data !=key2 && next2 !=NULL)
    {
    prev2 =temp2;
    temp2 =temp2->next;
    next2 =temp2->next;
    }
    if(next1 == NULL||next2 == NULL)
    return;

    prev1->next =temp2;
    temp2->next =next1;
    prev2->next =temp1;
    temp1->next =next2;
}
int main()
{
    struct Node *start = NULL;

    push(&start, 7);
    push(&start, 6);
    push(&start, 5);
    push(&start, 4);
    push(&start, 3);
    push(&start, 2);
    push(&start, 1);

    printf("\n Linked list before calling swapNodes() ");
    printList(start);

    swapNodes(&start, 4, 3);

    printf("\n Linked list after calling swapNodes() ");
    printList(start);

    return 0;
}

【问题讨论】:

  • 尝试在带有一些示例测试用例的调试器上运行。
  • 如果您被允许交换数据,那么您可以这样做以避免由于指针操作而导致的错误。
  • @ilz0R 你指出的参考对这个问题没有用。
  • @Bhart Mittal 该函数具有未定义的行为,因为 temp1 或 temp2 可以等于 NULL。
  • 虽然其中一个重复的问题被标记为 C++,但操作代码与 C 代码相同(但交换函数确实包含 cout &lt;&lt; … &lt;&lt; endl; 行,它是纯 C++)。这涵盖了更一般的情况;纯 C 问题涵盖了交换相邻节点的更有限的情况。请注意,C++ 问题中的建议之一是交换有效负载而不是交换指针——这具有很大的优点,因为它可以在不需要知道交换节点之前的任何节点的情况下完成。

标签: c data-structures linked-list swap singly-linked-list


【解决方案1】:

你应该重写你的swapNodes函数:

void swapNodes(struct Node** headr, int key1, int key2)
{
    struct Node* temp1 = *headr;
    struct Node* temp2 = *headr;

    if(key1==key2)
        return;

    struct Node* prev1=NULL;
    while(temp1 && temp1->data!=key1)
    {
        prev1=temp1;
        temp1=temp1->next;
    }
    struct Node* prev2=NULL;
    while(temp2 && temp2->data!=key2)
    {
        prev2=temp2;
        temp2=temp2->next;
    }

    if(temp1==NULL || temp1==NULL)
        return;

    // temp1 is a head
    if (prev1 == NULL) {
        *headr = temp2;
    } else {
        prev1->next = temp2;
    }

    // temp2 is a head
    if (prev2 == NULL) {
        *headr = temp1;
    } else {
        prev2->next = temp1;
    }

    struct Node *buff = temp2->next;
    temp2->next = temp1->next;
    temp1->next = buff;
}

如您所见,您不需要 next1next2 指针。但是您必须检查temp1temp2 是否为头:当您需要将头替换为另一个节点时,这是一种特殊情况。剩下的很简单——只需通过缓冲节点交换节点即可。

【讨论】:

    【解决方案2】:

    该函数具有未定义的行为,因为它没有考虑例如headr 可以等于NULLprev1prev2 可以等于NULL

    最好再写一个函数来查找与给定数据对应的节点。

    尽管如此,函数swapNodes 可以写成以下方式。它找到要交换的节点,然后交换指向节点及其数据成员next 的指针。

    你来了

    void swap( struct Node **first, struct Node **second )
    {
        struct Node *tmp = *first;
        *first = *second;
        *second = tmp;
    }
    
    void swapNodes( struct Node **headr, int key1, int key2 )
    {
        if ( key1 == key2 ) return;
    
        struct Node **first = headr;
    
        while ( *first && ( *first )->data != key1 ) first = &( *first )->next;
    
        if ( *first == NULL ) return;
    
        struct Node **second = headr;
    
        while ( *second && ( *second )->data != key2 ) second = &( *second )->next;
    
        if ( *second == NULL ) return;
    
        swap( first, second );
        swap( &( *first )->next, &( *second )->next );
    }
    

    这是一个演示程序。

    #include <stdio.h>
    #include <stdlib.h>
    
    struct Node
    {
        int data;
        struct Node *next;
    };
    
    void push(struct Node** head_ref, int new_data)
    {
        struct Node* new_node =
            (struct Node*) malloc(sizeof(struct Node));
    
        new_node->data  = new_data;
        new_node->next = (*head_ref);
        (*head_ref)    = new_node;
    }
    
    void printList(struct Node *node)
    {
        while(node != NULL)
        {
            printf("%d ", node->data);
            node = node->next;
        }
    }
    
    void swap( struct Node **first, struct Node **second )
    {
        struct Node *tmp = *first;
        *first = *second;
        *second = tmp;
    }
    
    void swapNodes( struct Node **headr, int key1, int key2 )
    {
        if ( key1 == key2 ) return;
    
        struct Node **first = headr;
    
        while ( *first && ( *first )->data != key1 ) first = &( *first )->next;
    
        if ( *first == NULL ) return;
    
        struct Node **second = headr;
    
        while ( *second && ( *second )->data != key2 ) second = &( *second )->next;
    
        if ( *second == NULL ) return;
    
        swap( first, second );
        swap( &( *first )->next, &( *second )->next );
    }
    
    int main( void ) 
    {
        struct Node *start = NULL;
    
        push(&start, 7);
        push(&start, 6);
        push(&start, 5);
        push(&start, 4);
        push(&start, 3);
        push(&start, 2);
        push(&start, 1);
    
        printf("\n Linked list before calling swapNodes() ");
        printList(start);
    
        swapNodes(&start, 4, 3);
    
        printf("\n Linked list after  calling swapNodes() ");
        printList(start);
    
        return 0;
    }
    

    它的输出是

     Linked list before calling swapNodes() 1 2 3 4 5 6 7 
     Linked list after  calling swapNodes() 1 2 4 3 5 6 7 
    

    事实上,函数swapNodes(没有为给定数据查找节点的单独函数)做了两件事:1)找到两个节点,2)交换它们。搜索节点可能不成功。所以该函数应该向用户报告节点是否被交换。在这种情况下,最好将函数声明为具有返回类型int

    例如

    int swapNodes( struct Node **headr, int key1, int key2 )
    {
        int success = key1 != key2;
    
        if ( success )
        {        
            struct Node **first  = headr;
            struct Node **second = headr;
    
            while ( *first && ( *first )->data != key1 ) first = &( *first )->next;
    
            success = *first != NULL;
    
            if ( success )
            {            
                while ( *second && ( *second )->data != key2 ) second = &( *second )->next;
    
                success = *second != NULL;
            }
    
            if ( success )
            {            
                swap( first, second );
                swap( &( *first )->next, &( *second )->next );
            }
        }
    
        return success;
    }
    

    如果像上面提到的那样编写一个单独的搜索节点的函数,那么交换节点的函数看起来会更清晰和简单。

    例如

    #include <stdio.h>
    #include <stdlib.h>
    
    struct Node
    {
        int data;
        struct Node *next;
    };
    
    void push(struct Node** head_ref, int new_data)
    {
        struct Node* new_node =
            (struct Node*) malloc(sizeof(struct Node));
    
        new_node->data  = new_data;
        new_node->next = (*head_ref);
        (*head_ref)    = new_node;
    }
    
    void printList(struct Node *node)
    {
        while(node != NULL)
        {
            printf("%d ", node->data);
            node = node->next;
        }
    }
    
    void swap( struct Node **first, struct Node **second )
    {
        struct Node *tmp = *first;
        *first = *second;
        *second = tmp;
    }
    
    struct Node ** find( struct Node **headr, int data )
    {
        while ( *headr && ( *headr )->data != data ) headr = &( *headr )->next;
    
        return headr;
    }
    
    void swapNodes( struct Node **first, struct Node **second )
    {
        swap( first, second );
        swap( &( *first )->next, &( *second )->next );
    }
    
    int main( void ) 
    {
        struct Node *start = NULL;
    
        push(&start, 7);
        push(&start, 6);
        push(&start, 5);
        push(&start, 4);
        push(&start, 3);
        push(&start, 2);
        push(&start, 1);
    
        printf("\n Linked list before calling swapNodes() ");
        printList(start);
    
        struct Node **first;
        struct Node **second;
    
        if ( ( first = find( &start, 4 ) ) && ( second = find( &start, 3 ) ) )  swapNodes( first, second );
    
        printf("\n Linked list after  calling swapNodes() ");
        printList(start);
    
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 2018-11-05
      • 1970-01-01
      • 2013-02-25
      • 1970-01-01
      • 2015-06-08
      • 1970-01-01
      • 2015-03-11
      • 1970-01-01
      相关资源
      最近更新 更多