在看到一个编程访问网站时,我遇到了交换链表中相邻元素的代码,但我发现它有点不对。以下是代码。
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。
答案 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
它将处理最后的节点:
cur->next
将阻止后续迭代,因此在退出循环之前,最后一个节点必须指向它之前的节点。答案 1 :(得分:2)
它测试它以确保它不是NULL
(最后一个元素)。不测试它将使您的程序遵循列表的最后一个元素的NULL指针。
tmp = next->next; /* If `next` is the last, `next->next` is NULL. */
答案 2 :(得分:2)
是的,你是对的,函数中有一个错误 - cur->next
在所有情况下都没有正确更新。
我个人发现本地变量名称tmp
和next
在next
的情况下并不特别有用且容易混淆。这些名字让我很难跟踪我在阅读该功能时所发生的事情。
我发现名称node1
,node2
和node3
可以让我更好地了解正在操纵哪个节点。如果其他人不同意我也不会感到惊讶。
这是我发现更具可读性的功能的重写版本,更重要的是我认为是正确的。
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;
}