【问题标题】:Swapping nodes in a linked list?交换链表中的节点?
【发布时间】:2018-11-05 15:16:19
【问题描述】:
我编写这个函数是为了交换链表中的 2 个节点,但结果是分段错误。你能检查一下吗?谢谢。
(我为 struct student* 做了 typedef 作为 punt)
void swap_node(punt node1, punt node2)
{
node1->next=node2->next;
node2->next=node1;
node2->prev=node1->prev;
node1->prev=node2;
(node2->prev)->next=node2;
}
【问题讨论】:
标签:
c
list
struct
linked-list
【解决方案1】:
我想这已经足够了,基本上与您的代码的唯一区别是最后一条语句(为简单起见,不包括空检查):
void swap_node(punt node1, punt node2)
{
node1->next=node2->next;
node2->next=node1;
(node1->prev)->next=node2;
node2->prev=node1->prev;
node1->prev=node2;
(node1->next)->prev=node1;
}
【解决方案2】:
如果可能,仅交换两个节点的内容会更容易交换两个节点。结果是一样的。如果您在代码中的其他地方持有一个指向您交换的节点之一的指针并且仍然期望它是同一个节点,这将造成问题。
无论如何,回到你的代码。有几件事需要细化。首先,我们需要检查node1 和node2 是否不为空,如果不是,我们可以继续,否则退出函数,因为我们不能交换它。交换代码的前 4 行没有问题,但这里有两个问题:
-
node1 之前的节点(交换之前)可能为 null,因此访问它的 next 指向 node2 的指针将导致未定义的行为并可能崩溃。检查它是否存在,然后执行分配。
- 您忘记检查
node2 之后是否存在节点(交换之前),如果存在,请将其指向prev 指针node1
【解决方案3】:
通常有助于将双向链表中的链接可视化,只需将其绘制在一张纸上即可。您会注意到每个节点有 4 个链接:
node->next
node->next->prev
node->prev
node->prev->next
所以要交换两个不相关的节点,您需要 交换 4 个链接。
以下将不起作用:
node1->next=node2->next;
这会覆盖旧值 node1-> next。您需要改用临时变量。像这样的:
#define SWAP_PTR(a,b) { void* tmp = b; b = a; a = tmp; }
void swap_node(punt node1, punt node2)
{
SWAP_PTR(node1->next, node2->next);
SWAP_PTR(node1->next->prev, node2->next->prev);
SWAP_PTR(node1->prev, node2->prev);
SWAP_PTR(node1->prev->next, node2->prev->next);
}
注意 - 在线程环境中,您需要某种形式的锁定。