24. 两两交换链表中的节点

本文介绍了一种链表中相邻节点两两交换的算法实现,通过增加前置指针简化操作流程,详细解释了交换过程中的关键步骤,并附带示例帮助理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、题目描述

给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。

你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

二、示例

示例 1:

输入:head = [1,2,3,4]
输出:[2,1,4,3]

示例 2:

输入:head = []
输出:[]

示例 3:

输入:head = [1]
输出:[1]

三、输入输出说明

链表中节点的数目在范围 [0, 100] 内
0 <= Node.val <= 100

四、基本思路

由于操作过程中会对第一个元素进行位置改变,所以在原head之前增加一个指针ans,使得ans->next = head,便可以进行后续操作

之后是进行两个元素的位置交换,通常画个图会不易出错,操作的时候记住:务必先记录即将断裂的部分,再进行断链操作

如图,在交换元素a,b的过程中,需要断开a与b的连接,于是先用中间变量指针t记录b:t = p->next->next

接下来断开b与后续元素的连接,于是记录b后续元素的位置:p->next->next = t->next,此步相当于将a与之前b的后续元素相连

由于b->next已经被记录,所以可以给b->next重新赋值:t->next = p->next,此步相当于完成了a与b的位置交换

然后将p与a,b进行连接以形成完整链:p->next = t

每次循环完成后更新p的位置,即向后移动两个元素,p = p->next->next = t->next

五、代码

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode *ans = new ListNode(-1);
        ans->next = head;
        ListNode *p = ans, *t;
        while (p->next != nullptr && p->next->next != nullptr) {
            t = p->next->next;
            p->next->next = t->next;
            t->next = p->next;
            p->next = t;
            p = t->next;
        }
        return ans->next;
    }
};

 

### C语言实现链表节点两两交换 为了在C语言中实现链表节点两两交换,可以采用迭代的方法。此方法通过引入一个虚拟头节点简化边界条件处理,并利用三个指针完成节点交换过程。 #### 定义链表结构体 首先定义单项链表的数据结构: ```c typedef struct ListNode { int val; struct ListNode *next; } ListNode; ``` #### 创建辅助函数用于创建新节点 这有助于测试和验证最终算法的功能: ```c ListNode* createNode(int value) { ListNode* newNode = (ListNode*)malloc(sizeof(ListNode)); newNode->val = value; newNode->next = NULL; return newNode; } ``` #### 主要逻辑:两两交换链中的节点 核心思路在于维护前驱节点`prev`、当前节点`first`以及后续节点`second`之间的关系,在遍历过程中不断调整这些指针的位置以达到交换目的[^3]。 ```c void swapPairs(ListNode **headRef) { // 如果列为空或只有一个元素,则无需任何操作直接返回原列 if (*headRef == NULL || (*headRef)->next == NULL) { return; } // 创建一个新的哨兵节点作为新的头部之前的一个位置 ListNode *dummyHead = createNode(0); dummyHead->next = *headRef; // `prev`始终指向待交换的一对节点之前的那个节点 ListNode *prev = dummyHead; while ((*headRef != NULL) && ((*headRef)->next != NULL)) { // 记录下一对需要处理的第一个节点 ListNode *first = *headRef; // 更新 head 指向第二节点之后的部分 *headRef = first->next->next; // 进行实际的节点交换 prev->next = first->next; // 将 prev 的 next 设置为 second first->next->next = first; // 把原来的第二个节点连接回第一个节点后面 first->next = *headRef; // 原来的第一个节点现在应该指向剩余部分 // 移动 prev 到刚刚被交换过的最后一个节点处准备下次循环 prev = first; } // 返回修改后的链表的新起点 *headRef = dummyHead->next; free(dummyHead); // 清理临时使用的哨兵节点 } ``` 上述代码实现了完整的两两交换功能,其中特别注意到了对于奇数长度链表最后剩下单独一个节点的情况也能够正确处理[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值