2011-08-13 47 views
3

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

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)有没有在我们的代码,我们不能在链表的末尾分配空值。

回答

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将阻止以下迭代,因此最后一个节点必须在退出循环之前由它指向的那个节点指向。
+0

感谢您的答复@Eran。我想,如果我们简单地删除这一行,如果(TMP),代码应该没有任何其他修改做工精细。 –

+0

@Amit,删除“if(tmp)”不会使它工作 - 你仍然在列表的末尾有一个循环,如果列表中有奇数个节点,你也会放弃最后一个。为了面试的缘故,我真的希望这段代码被故意弄糊涂了。在现实世界中,你最好将列表实现与其内容分开,并使用'std :: list '左右。将使交换数据变得如此容易...... – eran

+0

@Amit,只是想知道 - 你首先接受了这个答案,然后不接受它(或者叫做......)。为什么这不能回答你的问题的任何特殊原因? – eran

2

它测试它以确保它不是NULL(最后一个元素)。不测试它会使你的程序在列表的最后一个元素后面跟着NULL指针。

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

你看过我后期编辑 –

2

是的,你是对的,有一个功能的错误 - cur->next未在所有情况下正确更新。

我个人发现局部变量名称tmpnextnext的情况并不特别有帮助和积极混淆。这些名字让我很难在读完这个函数的时候跟踪我发生的事情。

我发现名称node1,node2node3对我来说能够更好地工作,以便让我更好地了解哪个节点正在被操作。但是,如果其他人不同意,我不会感到惊讶。

这里是我发现更具可读性,更重要的是我相信是正确的函数的修订版本。

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

Java实现

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

逻辑 1.第一 - 1,二 - 2,第三3
2. Second.next =第一
3.第一.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