你的算法是最好的。通常我们可以通过简单来获得一点速度。与其画图和推理指针,不如考虑从输入列表的头部弹出元素并使用队列添加到尾操作来构建结果。在伪代码中,我们有
set_empty(rtn);
while (head) {
fst = pop(head);
if (head) {
snd = pop(head);
add_at_tail(rtn, snd);
}
add_at_tail(rtn, fst);
}
if
仅需要防止输入列表具有奇数长度的情况。如果我们确定列表长度相等,我们可以跳过它。
现在 pop 很容易实现。如果我们使用虚拟头节点,则添加尾操作是最简单的。所以在 C 中,我们有:
node *swap(node *head)
{
node dummy[1]; // set_empty(rtn);
node *rtn = dummy;
while (head) {
node *fst = head; // fst = pop(head);
head = head->next;
if (head) {
node *snd = head; // snd = pop(head);
head = head->next;
rtn->next = snd; // add_to_tail(rtn, snd);
rtn = rtn->next;
}
rtn->next = fst; // add_to_tail(rtn, fst);
rtn = rtn->next;
}
rtn->next = NULL; // terminate tail
return dummy->next;
}
现在我还没有测试过这段代码,但我很确定它会以一个或两个错字为模运行良好。测试比你的少(每个元素只有一个)。测试相对昂贵,因为它们会干扰流水线,所以我的运行速度应该快一点。几乎可以肯定,这种差异是无关紧要的。
但是,我认为我的代码更容易理解。当然,这只是一种有偏见的观点,但在维护过程中,可读性确实很重要。
注意 现在我做了一个快速测试,第一次尝试就成功了!另一方面,当我尝试您的代码时,我得到了一个 segv
first->next=(third->next==NULL ? third : third->next);
下面是测试框架。你看有什么不对吗?
typedef struct node_s {
struct node_s *next;
int val;
} node;
// swap goes here
int main(void)
{
node dummy[1];
node *p = dummy;
for (int i = 0; i < 16; i++) {
p->next = malloc(sizeof(node));
p = p->next;
p->next = NULL;
p->val = 'a' + i;
}
p = swap(dummy->next);
while (p) {
printf("%c ", p->val);
p = p->next;
}
printf("\n");
return 0;
}