交换链表中的节点

时间:2013-01-08 00:01:17

标签: c linked-list swap

我有一个以这个值为例的链表:4 5 3 2 7,现在我想用前一个节点交换每个节点,如下所示:

4 5 3 2 7 // this beginning of list
5 4 3 2 7
5 3 4 2 7
5 3 2 4 7
5 3 2 7 4 // the list should now become like this

但不幸的是,当我解析输出时,我陷入无限循环:

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

typedef struct _node {
    int p;
    struct _node *next;
} node;

main(int argc, char **argv)
{
    int i, n;
    node *nod = NULL;
    node *nod_tmp = NULL;
    node *nod2 = NULL;
    printf("Enter n: ");
    scanf("%d", &n);
    for(i = 0; i < n; ++i)
    {
        nod_tmp = (node *)malloc(sizeof(node));
        scanf("%d", &nod_tmp->p);
        nod_tmp->next = nod;
        nod = nod_tmp;
    }

    i = 0;
    while(i < n)
    {   
        nod_tmp = nod;
        nod = nod->next;
        nod->next = nod_tmp;
        ++i;
    }

    while(nod != NULL)
    {   

        printf("%d\n", nod->p);
        nod = nod->next;
    }
    return 0;
}  

6 个答案:

答案 0 :(得分:2)

这看起来很奇怪:

while(i < n)
{   
    nod_tmp = nod;
    nod = nod->next;
    nod->next = nod_tmp;
    ++i;
}

基本上,您正在循环2个项目,将它们分配给彼此。你需要复习一下。

修改

确定为你写了,好像在工作。 (我是通过实际交换列表元素来实现的。)

/// reading and stuff...

node *prev = NULL, *start = nod->next;
for(int i = 0; i < n - 1; ++i)
{
    // look at this part, it makes everything obvious
    node *a = nod, *b = nod->next, *c = nod->next->next;

    b->next = a;
    a->next = c;

    nod = a; // changing the current node to next

    if(i == 0)
            {
        start = prev = b; // saving an actual start
            }
    else
    {
        prev->next = b;
        prev = prev->next;
    }

    // printing state to be sure
    for(node *tmp_start = start; tmp_start != NULL; tmp_start = tmp_start->next)
        printf("%d ", tmp_start->p);
    printf("\n");
}

printf("Final answer:\n");
while(start != NULL)
{   
    printf("%d ", start->p);
    start = start->next;
}

您需要以相反的顺序输入数据(或稍微更改读取功能)

使用示例:

Enter n: 5 7 2 3 5 4
5 4 3 2 7
5 3 4 2 7
5 3 2 4 7
5 3 2 7 4
Final answer:
5 3 2 7 4 

答案 1 :(得分:1)

您的交换代码错误。应该是这样的:

i = 1;
nod2 = nod;
while(i < n)
{   
    nod_tmp = nod2->next;
    nod2->next = nod_tmp->next;
    nod_tmp->next = nod2;
    ++i;
}

或者,因为交换每一对基本上都会将第一个元素推到最后,所以你可以这样做:

nod_tmp = nod;
while (nod_tmp->next != NULL)
{
    nod_tmp = nod_tmp->next;
}
// nod_tmp now points to the last element
nod_tmp->next = nod;          // loop from the last element back to the first
nod = nod->next;              // move the list pointer to the second element
nod_tmp->next->next = NULL;   // break the loop at the new last element

此外,您可能需要查看输入代码。如上所述,它将按照输入的相反顺序构建列表,因为它总是将下一个值添加到列表的头部。

<强>更新

为了避免潜在的seg_faults,可以在没有计数器的情况下重写上面的第一个循环:

nod2 = nod;
nod_tmp = nod2->next;
while(nod_tmp != NULL)
{   
    nod2->next = nod_tmp->next;
    nod_tmp->next = nod2;
    nod_tmp = nod2->next;
}

更新2

这是完整的代码,可以满足您的需求。它不是交换每对节点,而是将第一个节点推送到列表的末尾。我还修复了输入循环,以便按正确的顺序构建列表。

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

typedef struct _node {
    int p;
    struct _node *next;
} node;

main(int argc, char **argv)
{
    int i, n;
    node *nod = NULL;
    node *nod_tmp = NULL;
    node *nod2 = NULL;
    printf("Enter n: ");
    scanf("%d", &n);
    for(i = 0; i < n; ++i)
    {
        nod_tmp = (node *)malloc(sizeof(node));
        scanf("%d", &nod_tmp->p);
        if (i == 0)
        {
            nod = nod2 = nod_tmp;
        }
        nod2->next = nod_tmp;
        nod2 = nod_tmp;
    }

    nod_tmp = nod;
    while (nod_tmp->next != NULL)
    {
        nod_tmp = nod_tmp->next;
    }
    // nod_tmp now points to the last element
    nod_tmp->next = nod;          // loop from the last element back to the first
    nod = nod->next;              // move the list pointer to the second element
    nod_tmp->next->next = NULL;   // break the loop at the new last element

    while(nod != NULL)
    {   

        printf("%d\n", nod->p);
        nod = nod->next;
    }
    return 0;
}   

答案 2 :(得分:1)

让我们按照这个循环:

while(i < n)
{   
    nod_tmp = nod;         // 1
    nod = nod->next;       // 2
    nod->next = nod_tmp;   // 3
    ++i;
}
  1. nod_tmpnod现在指向同一个节点。
  2. nod现在指向nod->next(所以nod == nod_temp->next
  3. nod->next现在指向not_temp,这是nod的旧地址。
  4. 现在nod->next指向nod的旧地址(nod_temp也指向),你有一个链表,其尾部指向它的头部。

    这个while循环可能更适合你:

    nod2 = nod;
    nod_tmp = nod->next;
    while(nod_tmp != NULL)
    {   
        nod2->next = nod_tmp->next;
        nod_tmp->next = nod2;
        nod_tmp = nod2->next;
    }
    

答案 3 :(得分:0)

    i = 0;
    while(i < n)
    {
        printf("%d\n", nod->p);
        nod = nod->next;
        i++;
    }

答案 4 :(得分:0)

在完成交换之后和打印结果之前,您需要清除列表中最后一个条目的nod-&gt ;.

答案 5 :(得分:0)

c ++ 11 way ..

编译:g ++ --std = c ++ 11 -Wall -Wextra mylist.cpp

#include <iostream>
#include <list>

template <class List>
void print(const List& list) {
    for (auto i : list)
        std::cout << i << ' ';
    std::cout << std::endl;
}

template <class List>
void swap(List& list) {
    auto i(list.begin());
    auto next(i);
    auto end(list.end());
    while (++next != end) {
        auto tmp = *i;
        *i++ = *next;
        *i = tmp;
        print(list);
    }
}

int main(int, char**) {
    std::list<int> list {4, 5, 3, 2, 7};
    print(list);
    swap(list);
}