轻触节点,链表里的悄然邂逅

公主请阅

  • [1. 移除链表元素](#1. 移除链表元素)
    • [1. 题目说明](#1. 题目说明)
      • [示例 1](#示例 1)
      • [示例 2](#示例 2)
      • [示例 3](#示例 3)
    • [1.2 题目分析](#1.2 题目分析)
    • [1.3 代码部分](#1.3 代码部分)
    • [1.4 代码解析](#1.4 代码解析)
  • [2. 反转链表](#2. 反转链表)
    • [2. 1题目说明](#2. 1题目说明)
      • [示例 1](#示例 1)
      • [示例 2](#示例 2)
      • [示例 3](#示例 3)
    • [2.2 题目分析](#2.2 题目分析)
    • [2.3 代码部分](#2.3 代码部分)
    • [2.4 代码分析](#2.4 代码分析)

1. 移除链表元素


题目传送门


1. 题目说明

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。

示例 1

输入:head = [1,2,6,3,4,5,6], val = 6

输出:[1,2,3,4,5]


示例 2

输入:head = [], val = 1

输出:[]


示例 3

输入:head = [7,7,7,7], val = 7

输出:[]


1.2 题目分析

题目给了我们一个链表,要求说让我们将值等于val的链表删除,并且返回新的头结点

那么这个题我们该怎么进行解决呢?

我的想法是:我们可以通过设置一个哨兵位然后利用双指针进行链表的遍历,然后我们的两个指针如果在遍历过程中遇到了满足条件的节点的话,我们直接忽略了,将这个节点的前一个节点的next的指针进行改变,指向这个节点的下一个节点,通过这种方法我们间接的将这个节点删除了


1.3 代码部分

C 复制代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* removeElements(struct ListNode* head, int val)
{
    //创建一个哨兵节点(tmp),哨兵节点的next指针指向头结点
    struct ListNode*tmp=(struct ListNode*)malloc(sizeof(struct ListNode));
    tmp->next=head;

    //双指针
    struct ListNode*prev=tmp;//慢指针--当前节点的前一个节点,从哨兵卫开始
    struct ListNode*cur=head;//快指针遍历链表的当前节点,从头结点开始

    //遍历整个链表
    while(cur!=NULL)
    {
        if(cur->val==val)//如果当前节点的值等于val的话,那么我们就跳过当前节点
        {
            prev->next=cur->next;//当前遍历的节点的前一个节点的next将会直接指向当前节点的下个节点
            //就是说直接将当前节点忽略掉了
        }
        else//当前节点的值不等于val,那么我们继续往后移动
        {
            //移动prev
            prev=cur;
        }
        cur=cur->next;
    }
    //循环结束了,那么这个满足条件的节点就删除了

    //重新定义头结点,将哨兵卫忽略就行了
    struct ListNode*newHead=tmp->next;//用指针将头节点进行定义
    free(tmp);//释放哨兵卫
    return newHead;//返回我们之前保存的头结点的指针
}

1.4 代码解析

我们先利用malloc动态申请一个节点赋值给tmp,这个tmp就是我们所说的哨兵位,用来占位子的

然后我们的tmpnext指针就指向我们原先的头结点了

然后我们再创建两个指针:

  • prev---慢指针,当前节点的前一个节点,从哨兵位开始
  • cur---当前节点,从头结点开始

说明:我们的这个哨兵位仅仅是一个空节点,并不存在实际的数据的,我们创建出来只是用来占位子的

然后我们就可以进行遍历整个链表的操作了

遍历的循环条件是我们的当前节点cur不是空,就是只要到了尾节点我们就停下来了

我们在循环里面进行判断,如果当前节点的val满足条件的话,我们让这个节点的前一个节点指向这个节点的下一个节点,来达到间接删除当前的节点的作用

但是如果当前节点不满足的话我们就让prev这个指针赋值为cur

然后在这个while循环的结束位置,我们就进行移动的操作,进行链表节点的遍历操作

等循环结束了,我们这个链表中满足条件的val就间接被删除了

然后我们再重新定义头结点

头结点就是我们哨兵位的next指针指向的节点,这个时候我们的哨兵位的作用就发挥出来了

然后我们将哨兵位释放掉就行了,这个题就结束了


2. 反转链表


题目传送门


2. 1题目说明

这是 LeetCode 第 206 题:反转链表 的问题描述:

给定一个单链表的头节点 head,请你反转链表,并返回反转后的链表。

示例 1

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

示例 2

  • 输入: head = [1,2]
  • 输出: [2,1]

示例 3

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

限制条件

  • 链表中节点的数量范围是 [0, 5000]
  • -5000 <= Node.val <= 5000

2.2 题目分析

逆转链表顾名思义就是链表逆置

假设当前链表是1->2->3->4->5

逆置过后就是这个样子的5->4->3->2->1

那么我们怎么进行下面的操作呢?

我们还是使用双指针进行链表的遍历,关于这个逆置的操作我们在遍历的时候同时进行

同样是定义两个指针,然后在遍历的时候将当前的指向指向上一个节点,然后进行当前节点的改变,改变相邻两个节点的指针,随手遍历结束,我们的尾节点就变成了头结点,最后我们直接将头结点进行返回就行了

请看下面代码部分


2.3 代码部分

C 复制代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* reverseList(struct ListNode* head)
{
    struct ListNode*prev=NULL;//定义当前节点的前一个节点
    //因为反转后原始链表的头节点将成为新链表的尾节点,它的下一个节点应该指向 NULL。
    struct ListNode*cur=head;//用于遍历链表,从头结点开始

    while(cur!=NULL)//遍历链表
    {
        struct ListNode*nexttmp=cur->next;//保存当前节点的下一个节点

        //下面的两个代码就是对当前节点和当前节点的前面进行操作,进行指针逆转操作
        cur->next=prev;//当前节点的指针反转了,指向了前一个节点
        prev=cur;//当前节点变成了前一个节点了

        cur=nexttmp;//将cur移动到下一个节点的位置
    }
    //出了循环之后这个逆转操作就完成了
    return prev;//反转后的链表prev成为了新的头节点了
}

2.4 代码分析

我们先定义一个指针prev指向前一个节点,但是初始化我们设置为NULL,然后我们再定义一个指针cur指向当前的头节点head

然后我们使用while循环进行遍历链表,结束条件是遍历到尾节点就停止

我们在循环里面先定义一个指针nexttmp将当前节点的下个节点进行保存的操作

然后下面就是我们三个节点直接的指向变换了

我们让当前节点cur的下一个节点的指针next指向我们的前一个节点prev,然后我们让这个前一个节点prev变成我们的当前节点cur进行下一组相邻节点的逆置操作

然后我们让当前的cur变成我们当时保存的下一个节点的指针,我们现在对这两个节点进行逆置操作

随着循环结束,我们的最后prev就变成了新的头结点了

我们将这个节点返回操作就行了

相关推荐
Renas_TJOvO6 分钟前
排序算法汇总
java·数据结构·算法
Stardep8 分钟前
算法2—八大常用排序算法(下)
c语言·数据结构·笔记·算法·排序算法·1024程序员节
m0_629958341 小时前
数据结构,删除链表倒数第n个节点,并返回新的头节点
数据结构·链表
蓝夫人C++1 小时前
数据结构——单链表详解
c语言·数据结构
&ELove1 小时前
[数据结构]插入排序(全)
c语言·数据结构·排序算法
明月*清风1 小时前
【力扣专题栏】合并K个升序链表,3种解法讲解如何实现vector容器里面多个链表的合并?
算法·leetcode·链表
杜若南星1 小时前
保研考研机试攻略:python笔记(2)
数据结构·经验分享·笔记·python·考研·算法
wrx繁星点点2 小时前
原型模式:高效的对象克隆解决方案
数据结构·spring·spring cloud·java-ee·maven·intellij-idea·原型模式
何事驚慌4 小时前
2024/10/30 数据结构大题打卡
数据结构