如何在不交换数据的情况下交换单链表中的两个节点?
如何在不交换节点数据的前提下交换单链表中的两个节点?
嘿,这个问题问到点子上了——很多人一开始会直接怼节点的data字段,但既然要求只操作指针,那咱们就得把单链表的指针逻辑捋得明明白白,毕竟单链表的指针可是牵一发而动全身的。
先明确几个必须考虑的边界场景,不然很容易写出bug:
- 如果要交换的两个节点是同一个,直接返回就行,没必要折腾
- 如果其中一个节点是头节点,得单独处理(因为头节点没有前驱)
- 如果目标节点不存在于链表中,直接终止操作
话不多说,直接上完整的swapnodes函数实现,替换你原来的代码框架就行:
void swapnodes(int x, int y) { // 1. 如果x和y是同一个节点,无需交换 if (x == y) return; struct node *prevX = NULL, *currX = head; // 2. 查找x节点及其前驱节点 while (currX != NULL && currX->data != x) { prevX = currX; currX = currX->next; } struct node *prevY = NULL, *currY = head; // 3. 查找y节点及其前驱节点 while (currY != NULL && currY->data != y) { prevY = currY; currY = currY->next; } // 4. 如果x或y不存在于链表中,直接返回 if (currX == NULL || currY == NULL) return; // 5. 处理x是头节点的情况 if (prevX == NULL) { head = currY; } else { prevX->next = currY; } // 6. 处理y是头节点的情况 if (prevY == NULL) { head = currX; } else { prevY->next = currX; } // 7. 交换两个节点的next指针,完成位置互换 struct node *temp = currY->next; currY->next = currX->next; currX->next = temp; }
代码逻辑拆解:
- 步骤1:先过滤掉x和y相同的情况,避免做无用功
- 步骤2、3:遍历链表找到目标节点和它们的前驱——这是单链表操作的核心,因为要修改节点的指向,必须知道它前面的节点是谁
- 步骤4:如果其中一个节点找不到,直接终止操作,防止空指针访问
- 步骤5、6:处理头节点的特殊情况:如果目标节点是头节点,那么新的头节点就是另一个要交换的节点;否则就让前驱节点的
next指向另一个目标节点 - 步骤7:最后交换两个节点的
next指针,把它们各自的后续节点接对位置,这样整个链表的逻辑就通了
为了验证效果,你可以加个main函数测试:
int main() { head = NULL; // 从头部插入节点,最终链表是1->2->3->4->5 createnodeatbeg(5); createnodeatbeg(4); createnodeatbeg(3); createnodeatbeg(2); createnodeatbeg(1); printf("原链表:\n"); printlist(); // 测试交换头节点和尾节点 swapnodes(1, 5); printf("交换1和5后的链表:\n"); printlist(); // 测试交换相邻节点 swapnodes(2, 3); printf("交换2和3后的链表:\n"); printlist(); // 测试交换普通节点 swapnodes(1, 2); printf("交换1和2后的链表:\n"); printlist(); return 0; }
这个实现能覆盖所有常见场景,而且完全不需要交换节点的data字段,纯指针操作搞定。
内容的提问来源于stack exchange,提问作者nitishy2j
相关产品推荐
相关产品推荐

