交换链表中的相邻元素

时间:2011-08-13 13:20:06

标签: c linked-list

在看到一个编程访问网站时,我遇到了交换链表中相邻元素的代码,但我发现它有点不对。以下是代码。

void swap (struct list **list1)
{
    struct list *cur, *tmp, *next;
    cur = *list1;
    if (cur && cur->next)
        *list1 = cur->next;

    //To make sure that we have at least two more elements to be swapped.
    while (cur && cur->next)
    {
        next = cur->next;
        tmp = next->next;
        next->next = cur;
        //We have to make 1->next as 4 in above example (figure).

        if (tmp)
            cur->next = tmp->next;
        cur = tmp;
    }
    return;
}

现在对我来说,条件if (temp)不在这里。这种评估是否正确?

假设我们有一个链接列表,如:

  1->2->3->4->NULL

现在我们的目标是创建一个链接列表,如:

2->1->4->3->NULL

我担心如果我们的代码中有if (temp),我们就无法在链表的末尾指定null。

4 个答案:

答案 0 :(得分:4)

你是对的。这不起作用。它在列表的末尾创建一个循环,如果你在同一个列表上运行swap两次,第二次运行将进入无限循环。

要修复此笨拙的代码,请使用以下代码替换if (tmp)

if(tmp)
    if (tmp->next)
        cur->next = tmp->next;
    else
        cur->next = tmp;    // take care of an add number of nodes
else
    cur->next = NULL;   // take care of an even number of nodes

它将处理最后的节点:

  1. 如果存在偶数个节点,则确保最后指向NULL而不是之前的节点。
  2. 如果节点数量奇数,则检查cur->next将阻止后续迭代,因此在退出循环之前,最后一个节点必须指向它之前的节点。

答案 1 :(得分:2)

它测试它以确保它不是NULL(最后一个元素)。不测试它将使您的程序遵循列表的最后一个元素的NULL指针。

tmp = next->next; /* If `next` is the last, `next->next` is NULL. */

答案 2 :(得分:2)

是的,你是对的,函数中有一个错误 - cur->next在所有情况下都没有正确更新。

我个人发现本地变量名称tmpnextnext的情况下并不特别有用且容易混淆。这些名字让我很难跟踪我在阅读该功能时所发生的事情。

我发现名称node1node2node3可以让我更好地了解正在操纵哪个节点。如果其他人不同意我也不会感到惊讶。

这是我发现更具可读性的功能的重写版本,更重要的是我认为是正确的。

void swap (struct list **head)
{
    struct list *node1 = *head;
    struct list *node2 = node1 ? node1->next : NULL;

    // handle degenerate cases
    if (!node2) {
        // no elements or only one element on the list
        //  nothing to do...
        return;
    }    

    // fix-up list head to what will be the new first node on list
    *head = node2;        

    // while there are at least 2 more elements to be swapped
    while (node1 && node2) {
        struct list* node3 = node2->next;

        // get a pointer to the node that will be the remainder of the
        //  list after the remainder of the list is processed.  
        //
        // This will be NULL, node3, or 'node4' depending on whether 
        //  there are 0 , 1 or 2+ nodes following node1 and node2
        struct list* remainder = (node3 && node3->next) ? node3->next : node3;

        node1->next = remainder;
        node2->next = node1;

        // prepare pointers to the next two nodes to be swapped
        node1 = node3;
        node2 = node3 ? node3->next : NULL;
    }

    return;
}

答案 3 :(得分:0)

Java实施

鉴于:1->2->3->4->5->6

逻辑  1.第一,第二,第二,第三,第三  2. Second.next =第一个  3. First.next = Third.next取决于偶数或奇数更新

public ListNode evenOddMerge(ListNode head) {

        if (head == null || head.next == null) {
            return head;
        }

        ListNode first = head;
        ListNode second = first.next;
        ListNode third = null;

        head = second;

        while (true) {

            third = second.next;

            second.next = first;

            if (third == null || third.next == null) {
                first.next = third;
                break;
            }

            first.next = third.next;

            first = third;
            second = first.next;
        }

        return head;
    }

致谢:Geeks for Geeks