首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

尝试在没有双指针的纯C语言中交换链表中的两个相邻节点

在没有双指针的纯C语言中交换链表中的两个相邻节点,可以使用以下步骤:

  1. 首先,判断链表的头节点是否为空,如果为空则直接返回。
  2. 定义三个指针,分别为prev、curr和next。prev指向当前节点的前一个节点,curr指向当前节点,next指向当前节点的后一个节点。
  3. 判断链表的头节点是否为要交换的节点之一,如果是,则需要重新调整链表的头节点。若不是,则开始遍历链表。
  4. 进入循环遍历链表,每次迭代中,交换curr和next节点的位置。
  5. 在交换节点位置之前,需要判断next节点是否为空,如果为空则说明已经到达链表末尾,无法再交换节点了。在交换节点之前,还需要判断prev节点是否为空,如果为空则说明curr节点为头节点,需要重新调整链表的头节点。
  6. 完成节点交换后,将prev指向next节点,将curr指向next节点的下一个节点。
  7. 继续进行下一轮的节点交换,直到遍历完整个链表。

下面是使用纯C语言实现交换链表中两个相邻节点的示例代码:

代码语言:txt
复制
#include <stdio.h>
#include <stdlib.h>

// 定义链表节点结构体
struct ListNode {
    int val;
    struct ListNode* next;
};

// 创建链表节点
struct ListNode* createNode(int val) {
    struct ListNode* newNode = (struct ListNode*)malloc(sizeof(struct ListNode));
    newNode->val = val;
    newNode->next = NULL;
    return newNode;
}

// 交换链表中两个相邻节点
struct ListNode* swapNodes(struct ListNode* head) {
    if (head == NULL || head->next == NULL) {
        return head;
    }

    struct ListNode* prev = NULL;
    struct ListNode* curr = head;
    struct ListNode* next = head->next;

    // 判断链表头节点是否为要交换的节点
    if (curr->val > next->val) {
        head = next;
    }

    while (next != NULL) {
        curr->next = next->next;
        next->next = curr;
        
        if (prev != NULL) {
            prev->next = next;
        }
        
        prev = curr;
        curr = curr->next;
        
        if (curr != NULL) {
            next = curr->next;
        } else {
            next = NULL;
        }
        
        if (next != NULL && curr->val > next->val) {
            prev->next = next;
            head = next;
        }
    }

    return head;
}

// 打印链表
void printList(struct ListNode* head) {
    struct ListNode* curr = head;
    while (curr != NULL) {
        printf("%d ", curr->val);
        curr = curr->next;
    }
    printf("\n");
}

int main() {
    // 创建链表
    struct ListNode* head = createNode(1);
    head->next = createNode(2);
    head->next->next = createNode(3);
    head->next->next->next = createNode(4);
    head->next->next->next->next = createNode(5);

    // 打印原始链表
    printf("原始链表:");
    printList(head);

    // 交换相邻节点
    head = swapNodes(head);

    // 打印交换后的链表
    printf("交换后的链表:");
    printList(head);

    return 0;
}

在以上示例代码中,我们使用了三个指针prev、curr和next来交换链表中的相邻节点,通过迭代遍历链表,并根据节点的值大小进行相应的节点交换操作。最后打印出交换后的链表。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

力扣每日一刷(2023.10.2)

思路 本题有两种解法 ,一种是直接使用双指针来改变节点的指向; 另一种就是使用栈来进行一次进出栈 使用双指针 首先定义一个虚拟头节点pre, 置为空,然后定义一个nextNode指针, 用于指向当前节点的下一个...,两两交换其中相邻的节点,并返回交换后链表的头节点。...[0, 100] 内 0 <= Node.val <= 100 思路: 这道题本质上和反转链表是一个道理, 都是通过改变节点指针的方向来实现的, 不过本题只需要改变相邻的两个即可。...如果两个链表不存在相交节点,返回 null 。 图示两个链表在节点 c1 开始相交: 题目数据 保证 整个链式结构中不存在环。 注意,函数返回结果后,链表必须 保持其原始结构 。...— 请注意相交节点的值不为 1,因为在链表 A 和链表 B 之中值为 1 的节点 (A 中第二个节点和 B 中第三个节点) 是不同的节点。

8710

JavaScript刷LeetCode拿offer-高频链表题

,在 JS 中可以表现为一个拥有 val 和 next 属性的对象,所以遇到形如交换两个链表节点的时候,千万不能交换两个链表的 val 值,虽然 LC 有一些题是可以过,但是实际上是不合理的,而且一旦出现这种思想...相交链表 就会理解不了;记住,链表是一个数据结构,不是一个值,可以类比成一个对象,交换链表比如不是简单交换值;都是中等题这里选的都是按照 LC 火热排序,中等难度的题,感觉纯链表学习做特别难没太大必要,...,但是在 LC 的链表序列化中以数组的形式存在,就会迷惑为什么不是在 aTail 这个节点就是相交节点,需要特别注意所以我们一起走两个链表,直到其中一个结束,找出可能剩下没走完的那个链表,就可以判断除...交换链表中的节点分析先用双指针求出正序第 k 个节点 first 和反序第 k 个节点 second现在要交换 first 和 second , 需要先判断他们两个节点是不是相邻,相邻节点可以直接处理如果不是相邻节点...链表中的下一个更大节点分析 -- 双指针写指针 w 遍历整个链表,读指针 r 找到第一个比当前 w 大的节点,并返回对应的值,如果 r 走完整个链表没找到,则返回 0这题和上一题一样,都是循环遍历,找到符合要求的值

40120
  • JavaScript刷LeetCode拿offer-高频链表题1

    ,在 JS 中可以表现为一个拥有 val 和 next 属性的对象,所以遇到形如交换两个链表节点的时候,千万不能交换两个链表的 val 值,虽然 LC 有一些题是可以过,但是实际上是不合理的,而且一旦出现这种思想...相交链表 就会理解不了;记住,链表是一个数据结构,不是一个值,可以类比成一个对象,交换链表比如不是简单交换值;都是中等题这里选的都是按照 LC 火热排序,中等难度的题,感觉纯链表学习做特别难没太大必要,...,但是在 LC 的链表序列化中以数组的形式存在,就会迷惑为什么不是在 aTail 这个节点就是相交节点,需要特别注意所以我们一起走两个链表,直到其中一个结束,找出可能剩下没走完的那个链表,就可以判断除...交换链表中的节点分析先用双指针求出正序第 k 个节点 first 和反序第 k 个节点 second现在要交换 first 和 second , 需要先判断他们两个节点是不是相邻,相邻节点可以直接处理如果不是相邻节点...链表中的下一个更大节点分析 -- 双指针写指针 w 遍历整个链表,读指针 r 找到第一个比当前 w 大的节点,并返回对应的值,如果 r 走完整个链表没找到,则返回 0这题和上一题一样,都是循环遍历,找到符合要求的值

    35230

    JavaScript刷LeetCode拿offer-高频链表题1

    ,在 JS 中可以表现为一个拥有 val 和 next 属性的对象,所以遇到形如交换两个链表节点的时候,千万不能交换两个链表的 val 值,虽然 LC 有一些题是可以过,但是实际上是不合理的,而且一旦出现这种思想...相交链表 就会理解不了;记住,链表是一个数据结构,不是一个值,可以类比成一个对象,交换链表比如不是简单交换值;都是中等题这里选的都是按照 LC 火热排序,中等难度的题,感觉纯链表学习做特别难没太大必要,...,但是在 LC 的链表序列化中以数组的形式存在,就会迷惑为什么不是在 aTail 这个节点就是相交节点,需要特别注意所以我们一起走两个链表,直到其中一个结束,找出可能剩下没走完的那个链表,就可以判断除...交换链表中的节点分析先用双指针求出正序第 k 个节点 first 和反序第 k 个节点 second现在要交换 first 和 second , 需要先判断他们两个节点是不是相邻,相邻节点可以直接处理如果不是相邻节点...链表中的下一个更大节点分析 -- 双指针写指针 w 遍历整个链表,读指针 r 找到第一个比当前 w 大的节点,并返回对应的值,如果 r 走完整个链表没找到,则返回 0这题和上一题一样,都是循环遍历,找到符合要求的值

    45850

    JavaScript刷LeetCode--高频链表题

    ,在 JS 中可以表现为一个拥有 val 和 next 属性的对象,所以遇到形如交换两个链表节点的时候,千万不能交换两个链表的 val 值,虽然 LC 有一些题是可以过,但是实际上是不合理的,而且一旦出现这种思想...相交链表 就会理解不了;记住,链表是一个数据结构,不是一个值,可以类比成一个对象,交换链表比如不是简单交换值;都是中等题这里选的都是按照 LC 火热排序,中等难度的题,感觉纯链表学习做特别难没太大必要,...,但是在 LC 的链表序列化中以数组的形式存在,就会迷惑为什么不是在 aTail 这个节点就是相交节点,需要特别注意所以我们一起走两个链表,直到其中一个结束,找出可能剩下没走完的那个链表,就可以判断除...交换链表中的节点分析先用双指针求出正序第 k 个节点 first 和反序第 k 个节点 second现在要交换 first 和 second , 需要先判断他们两个节点是不是相邻,相邻节点可以直接处理如果不是相邻节点...链表中的下一个更大节点分析 -- 双指针写指针 w 遍历整个链表,读指针 r 找到第一个比当前 w 大的节点,并返回对应的值,如果 r 走完整个链表没找到,则返回 0这题和上一题一样,都是循环遍历,找到符合要求的值

    53660

    精读《算法 - 滑动窗口》

    双指针也并不局限在数组问题,像链表场景的 “快慢指针” 也属于双指针的场景,其快慢指针滑动过程中本身就会产生一个窗口,比如当窗口收缩到某种程度,可以得到一些结论。...一般双指针是暴力算法的优化版,所以: 如果题目较为简单,且是数组或链表问题,往往可以尝试双指针是否可解。 如果数组存在规律,可以尝试双指针。...题目如下: 给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。...链表中倒数第k个节点 链表中倒数第k个节点是一道简单题,题目如下: 输入一个链表,输出该链表中倒数第 k 个节点。为了符合大多数人的习惯,本题从 1 开始计数,即链表的尾节点是倒数第 1 个节点。...这道题双指针的移动规则比较巧妙,与上面普通题目不一样,重点不是在是否会运用滑动窗口算法,而是能否找到移动指针的规则。 当然你可能会说,为什么两个指针要定义在最两端,而非别的地方?

    62420

    数据结构:一般线性表

    顺序表 顺序表的特点是表中元素的逻辑顺序与其物理顺序相同 特点: 最主要特点是可以进行随机访问,即通过首地址和元素序号可以在O(1)时间内找到指定元素 存储密度高,每个结点只存储数据元素 逻辑上相邻的元素物理上也相邻...单链表 线性表的链式存储又称为单链表,它是通过一组任意的存储单元来存储线性表中的数据元素。为了建立数据与元素之间的线性关系,对每个链表节点,除了存放元素自身的信息之外,还需要一个存储指向其后继的指针。...data为数据域,存放数据元素;next为指针域,存放其后继节点的地址。 image.png 为了操作上方便,在单链表的第一个节点之前附加一个节点,称为头结点。...双链表 3. 循环链表 循环单链表:循环单链表和单链表的区别在于,表中最后一个节点的指针不是NULL,而是指向头结点 循环双链表: 4....总体来说静态链表没有单链表使用起来方便,但是在一些不支持指针的高级语言中,这是一种非常巧妙的方法。

    96431

    力扣刷题篇——链表篇

    目录  两两交换链表的结点 题目描述: 解题思路: 代码如下: 删除链表的倒数第N个结点 题目描述: 图解 :  代码附上:  友友们 大家好呀 我是你们的小王同学 今天小王同学给大家带来两道经典的链表练习...两两交换链表中的节点 - 力扣(LeetCode) 题目描述:  解题思路: 根据题意要求 不能单纯的改变节点内部的值,并且需要将实际的节点进行交换 这道题小王同学采用的是递归的方式 具体的操作看小王的代码...此时不需要交换咱们的相邻的节点 直接返回 头节点就行了 if(head==null||head.next==null) return head; //获取当前节点的下一个节点...删除链表的倒数第 N 个结点 题目描述: 解题思路:  这道题就是一道经典的双指针的题型,如果我们要删除倒数第N个节点 定义两个指针 fast 和slow 让fast移动n步,然后让fast和slow...图解 : 定义fast和slow两个指针,初始化值为虚拟头结点 我们以第一个n=2为例子来解释  第一步: 第二步:   首先让我们的fast指针先走n+1步 这里的n为2,n+1的原因是这样slow

    19820

    【一个神奇的数据结构-异或双链表】拥有单链表的空间,效率如双链表

    在最开始学编程的时候,我们交换两个变量,有两种方法//方法一c=aa=bb=c//方法二a=a+bb=a-ba=a-b从第二种方法我们可以看出,我们可以通过两个数的相加,然后特别取出某个数那么想一想?...思路和上面通过加法有点像双链表看这个的应该都会,我直接上图我们把中间某一个节点单独提取出来,就会是这样其中prev是上一个节点的地址,next是下一个节点的地址属于两个指针域,那么我们能否用一个指针域来代替两个呢如果能够代替...,那么假设我们某个节点的前驱节点地址如果是已知的,那么他的后继节点地址也能够退出来,比如我们可以设当前节点的指针与为prev+next,然后上一个节点的地址是prev,那么下一个节点的地址不就是prev...⊕ addr(C)获取B的后继C的地址addr(C) = B->xorPtr ⊕ addr(A)通过以上的几种操作,就可以遍历整个链表,在处理添加、插入、删除等操作时同普通的双向链表类似注意:这些异或和加法相关的操作都是针对指针值的本身...*xorptr=NULL;//存储相邻两个节点地址的异或值}Node;inline Node* xorp(Node* a, Node* b){ return (Node *)((unsigned

    59933

    —-对双向链表中结(节)点的成员排序(冒泡排序)「建议收藏」

    双向链表的定义 ---- 【百度百科】 双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。...所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。 链表中的每个节点的成员由两部分组成: 1. 数据域:专门用来保存各个成员的信息数据。 2....双向链表中节点的成员排序(冒泡排序) ---- 在排序之前我们需要明确一点:的链表的头节点的数据域是否写有数据> 因为有时候程序员写代码时为了链表方便操作会专门创建一个表头(头结点),即不存放数据的表头...p总是在Pn的前面,那也就是说满足交换位置条件之后进行位置交换,交换之后两个临时指针位置就随之交换,在交换的过程中,假如有尾结点,那么pn的后向指针指向NULL,随之 pn->pnext->prev 就会出现段错误...//定义两个临时指针来进行数据处理 PSTU p1=head; //p和pn总是两个相邻的节点,且pn在

    1K40

    双指针法:总结篇!

    所以此时使用双指针法才展现出效率的优势:「通过两个指针在一个for循环下完成两个for循环的工作。」...使用双指针法,「定义两个指针(也可以说是索引下表),一个从字符串前面,一个从字符串后面,两个指针同时向中间移动,并交换元素。」,时间复杂度是O(n)。...思路还是很简单的,代码也不长,但是想在白纸上一次性写出bugfree的代码,并不是容易的事情。 在链表中求环,应该是双指针在链表里最经典的应用,在链表:环找到了,那入口呢?...「使用快慢指针(双指针法),分别定义 fast 和 slow指针,从头结点出发,fast指针每次移动两个节点,slow指针每次移动一个节点,如果 fast 和 slow指针在途中相遇 ,说明这个链表有环...中,讲到使用哈希法可以解决1.两数之和的问题 其实使用双指针也可以解决1.两数之和的问题,只不过1.两数之和求的是两个元素的下标,没法用双指针,如果改成求具体两个元素的数值就可以了,大家可以尝试用双指针做一个

    1.6K10

    【数据结构】-----双链表(小白必看!!!)

    c语言中的小小白-CSDN博客c语言中的小小白关注算法,c++,c语言,贪心算法,链表,mysql,动态规划,后端,线性回归,数据结构,排序算法领域. https://blog.csdn.net/bhbcdxb123...双链表的结点中有两个指针prior和next,分别指向前驱结点和后继结点。  ...由于每个节点都有指向前一个节点的指针,可以从任一节点开始向前或向后遍历链表,这对于某些操作如逆序遍历或者在特定节点前后插入节点非常方便。 其次,双链表更便于节点的删除和插入。...在单链表中,要删除或插入一个节点,需要找到其前一个节点,而在双链表中,只需要修改节点本身的指针即可,无需额外的查找操作,从而提高了操作效率。...然而,双链表相比单链表需要额外的空间来存储前一个节点的指针,因此会占用更多的内存。在某些情况下,如果对内存占用有限制,可能需要权衡选择是否使用双链表。

    9610

    Redis系列(二)底层数据结构之双端链表

    我读了几本 Redis 相关的书籍,尝试去了解它的具体实现,将一些底层的数据结构及实现原理记录下来。 本文将介绍 Redis 中最基础的 linkedlist(双端链表) 的实现方法。...定义 链表,是一个非常常用的数据结构,在很多编程语言里都有实现,比如 Java 中的 LinkedList. 但是 C 语言没有。...带有头指针和尾指针 在 list 结构中,保存了当前链表的表头指针和表尾指针,因此可以快速的从头进行遍历或者从尾部开始遍历。...带有长度计数器 list 结构中保存了当前链表长度的长度,因此对链表长度的统计时间复杂度是 O(1). 总结 链表是一个比较常用的数据结构,在很多编程语言中都有实现,读者们接触也很多。...因此本文没有专门去强调它的实现方法,而是大概介绍了下 Redis 中的链表的一个结构及其主要特性: Redis 的链表是双端链表。 封装了 list 结构,保存了链表的头尾指针以及链表长度。

    73120

    数据结构(2):链表(上)

    引入头结点后,可以带来两个优点: 由于第一个数据结点的位置被存放在头结点的指针域中,所以在链表的第一个位置上的操作和在表的其他位置上的操作一致,无需进行特殊处理。...为了克服单链表的上述缺点,引入了双链表,双链表结点中有两个指针 prior 和 next,分别指向其前驱结点和后继结点。...= self.next = None # 前驱和后继指针 双链表在单链表的结点中增加了一个指向其前驱的 prior 指针,因此双链表中的按值查找和按位查找的操作与单链表的相同,但双链表在插入和删除操作的实现上...循环链表 循环单链表 ? 在循环单链表中,表尾结点 r 的 next 域指向 L,故表中没有指针域为 None 的结点,因此,循环单链表的判空条件不是头结点的指针是否为空,而是它是否等于头指针。...循环双链表 由循环单链表的定义不难推出循环双链表。不同的是在循环双链表中,头结点的 prior 指针还要指向表尾结点,如图所示。 ?

    89810

    前端学数据结构与算法(四):理解递归及拿力扣链表题目练手

    再解决链表问题时,如果没有思路,可以用纸和笔把指针指向的过程画下来,然后再尝试从里面找到重复子问题会很有帮助。 206....两两交换链表中的节点↓ 给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。...如果尝试用纸和笔画出过程,就很容易发现子问题,让第一个节点指向第二个节点之后已经交换好的链表,然后让第二个节点指向之前的节点。...1->2->3->4->5 返回3->4->5 设置两个指针,慢指针一次走一步,快指针一次走两步,当快指针走完时,正好慢指针在链表的中间。...环形链表↓ 给定一个链表,判断链表中是否有环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。

    59200

    文心一言 VS 讯飞星火 VS chatgpt (157)-- 算法导论12.3 4题

    文心一言: 在Go语言中,删除操作是不可交换的。这意味着先删除节点 x 再删除节点 y 与先删除节点 y 再删除节点 x 留下的结果树可能不同。...在这里插入图片描述 智谱清言: 在Go语言中,删除操作在大多数数据结构中是不可交换的,因为删除操作通常依赖于元素的索引或位置。...让我们举一个反例来说明删除操作在Go语言中的不可交换性: 假设我们有一个整数切片 [1, 2, 3, 4, 5],我们将尝试删除元素 2 和 3。...切片:删除操作也不是可交换的,原因与数组相同。 3. 链表:对于链表,删除操作通常是可交换的。因为链表中的每个节点都有一个指向下一个节点的指针,所以删除操作只会影响被删除节点和其相邻节点。...在这里插入图片描述 天工: 在Go语言中,删除操作不可交换。原因如下: 假设我们有两个有序的元素x和y,我们想要删除x和y。 1.

    13620

    【递归、搜索与回溯算法练习】day2

    两两交换链表中的节点 1.题目简介 24. 两两交换链表中的节点 给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。...你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。...2.解题思路 递归思路: 先处理第二个节点之后的节点,再将前两个节点进行交换,最后连接后面处理好的节点 迭代思路: 双指针法(三指针法) 两个指针进行交换,第三个指针进行遍历,直到将链表遍历结束...cur = head -> next,* next = cur -> next; ListNode* newhead = cur; int flag = 1;//假设链表的节点个数为偶数...while(next) { cur -> next = prev; if(next -> next)//链表的节点个数是偶数个或者未到达链表结尾

    12810

    代码随想录day02--链表

    思路是使用虚拟节点的方式比较简单一些,直接定义一个虚拟节点指向头结点,在链表中移除元素就是将指针域向后移动两部就可 代码 /** * Definition for singly-linked list...addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。 addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val 的节点。...题目 地址:两两交换链表中的节点 给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。...如果两个链表没有交点,返回 null 。 简单来说,就是求两个链表交点节点的指针。 这里要注意,交点不是数值相等,而是指针相等。...如果链表无环,则返回 null。 为了表示给定链表中的环,使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。

    5510

    Leetcode链表题目总结

    注意: 如果两个链表没有交点,返回 null 。 在返回结果后,两个链表仍须保持原有的结构。 可假定整个链表结构中没有循环。 程序尽量满足 O(n) 时间复杂度,且仅用 O(1) 内存。...题目描述   给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。...解题思路   本题需要两两交换链表中相邻的节点,这说明在在整个过程中都是功能相同的操作,这让我们就很自然的想到使用递归的方式去处理。...两个链表的第一个公共节点 题目描述   输入两个链表,找出它们的第一个公共节点。   如下面的两个链表: ?   在节点 c1 开始相交。 示例 1: ?...注意: 如果两个链表没有交点,返回 null. 在返回结果后,两个链表仍须保持原有的结构。 可假定整个链表结构中没有循环。 程序尽量满足 O(n) 时间复杂度,且仅用 O(1) 内存。

    58220

    TypeScript算法题实战——链表篇(链表的设计、反转、两两交换、删除、相交和环形链表)

    链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针的意思),链表的类型有单链表、双链表、循环链表...您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性:val 和 next。val 是当前节点的值,next 是指向下一个节点的指针/引用。...在链表类中实现这些功能:get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。...5.1、题目描述力扣链接:https://leetcode.cn/problems/swap-nodes-in-pairs/给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。...如果两个链表没有交点,返回 null 。

    19010
    领券