【链表】一起学链表,熟练掌握链表的各种操作

0 勇士救主的故事

公主被巨龙 昆图库塔卡提考特苏瓦西拉松 抓走了,勇士 达拉崩吧斑得贝迪卜多比鲁翁 出发去救公主

勇士 达拉崩吧斑得贝迪卜多比鲁翁 到了 拉西卡帕斯蒂谷鹏大草原,发现了去往 西路伽什材科安丰黑森林 的道路;

勇士 达拉崩吧斑得贝迪卜多比鲁翁 到了 西路伽什材科安丰黑森林,发现了去往 哲石亦作步纸明子风雪山 的秘密;

勇士 达拉崩吧斑得贝迪卜多比鲁翁 到了 哲石亦作步纸明子风雪山,发现了去往 巨龙山洞 的秘密;

最后勇士 达拉崩吧斑得贝迪卜多比鲁翁 打败了巨龙 昆图库塔卡提考特苏瓦西拉松 ,就出了公主 公主米娅莫拉苏娜丹妮谢莉红

结束,这就是勇士救公主的故事

附上地图:
在这里插入图片描述
简单来说呢,就是从 A 找到了去 B 的路,从 B 找到了去 C 的路,从 C 找到了去D的路

1 链表的介绍

链表是一种 线性表 ,链表中的数据存储在一个个的 节点 里,节点 不一定是连续存储的,在每一个 节点 中,除了存储数据以外,还会存储下一个 节点位置信息(内存地址),根据此 位置信息(链接) 可以找到下一个 节点

2 链表的特点

2.1 优点

数据的插入和删除都相当方便,有新数据插入就向系统申请一块内存空间,而数据被删除后,就可以把这块内存空间还给系统,加入和删除都不需要移动大量的数据。

2.2 缺点

设计数据结构时比较麻烦,并且在查找数据时,也无法像静态数据(如数组)那样可以随机读取数据,必须要按序查找到该数据为止。

2.3 复杂度

在这里插入图片描述

3 单链表的增操作和删操作

3.1 单链表节点的数据结构

    class ListNode {
        int val;
        ListNode next;
        ListNode(int x) {
            val = x;
            next = null;
        }
    }

3.2 增

在这里插入图片描述
node 节点后插入 target 节点分两步:

第一步,把 targetnext 指针指向 nodenext 节点上

target.next = node.next

在这里插入图片描述
第二步,把 nodenext 指针指向 target 指针

node.next = target

在这里插入图片描述

3.3 删

在这里插入图片描述
要删除 node 候面的 target 节点,只需要一步,把 nodenext 指针指向 targetnext 指针指向的节点上即可

node.next = target.next

在这里插入图片描述

4 双链表的增操作和删操作

4.1 双链表节点的数据结构

    class ListNode {
        int val;
        ListNode next;
        ListNode pre;
        ListNode(int x) {
            val = x;
            next = null;
            pre = null;
        }
    }

4.2 增

在这里插入图片描述
在双链表 node 后边插入一个 target 节点,需要执行四步操作:

第一步,把 targetnext 指针指向 nodenext 指针指向的对象

target.next = node.next
在这里插入图片描述

第二步,把nodenext指向的对象的pre指针指向 target

node.next.pre = target
在这里插入图片描述

第三步,把 targetpre 指针指向 node 节点

target.pre = node
在这里插入图片描述

第四步,把 nodenext 指针指向 target 节点

node.next = target
在这里插入图片描述

4.3 删

在这里插入图片描述
在双链表中删除 target 节点分两步:

第一步,把 target 节点的 next 指针指向的节点的 pre 指针指向 node

target.next.pre = node
在这里插入图片描述

第二步,把 nodenext 指针指向 targetnext 指针指向的节点

node.next = target.next
在这里插入图片描述

5 实现链表

5.1 链表的几个方法

int get(int index) 获取指定 index 的元素

void addAtHead(int val) 添加元素到链表头部

void addAtTail(int val) 添加元素到链表尾部

void addAtIndex(int index, int val) 添加元素到链表指定 index

void deleteAtIndex(int index) 删除链表指定 index 的元素

5.2 code

设计链表的实现。链表中的节点应该具有两个属性:valnextval 是当前节点的值,next 是指向下一个节点的指针引用。

class MyLinkedList {
    private ListNode Head;
    int size;

    public MyLinkedList() {
        Head = new ListNode(0); // 初始化头节点
        size = 0; // 初始化链表大小
    }

    // 获取指定 index 的元素
    public int get(int index) {
        if (index < 0 || index >= size) return -1; // 如果 index 在索引之外,直接返回 -1
        ListNode curr = Head.next;
        for (int i = 0; i < index; i++) curr = curr.next; // 遍历找到我们需要的位置
        return curr.val;
    }

    // 添加元素到链表头部
    public void addAtHead(int val) {
        addAtIndex(0, val);
    }

    // 添加元素到链表尾部
    public void addAtTail(int val) {
        addAtIndex(size, val);
    }

    // 添加元素到链表指定 index 处
    public void addAtIndex(int index, int val) {
        if (index < 0  index > size) return; // 如果 index 在索引之外,直接返回
        ListNode pre = Head;
        for (int i = 0; i < index; i++) pre = pre.next; // 循环遍历,找到插入位置的前一个节点
        ListNode node = new ListNode(val); // 拿到前一个节点,下面执行的是插入操作
        node.next = pre.next;
        pre.next = node;
        size++;
    }

    // 删除链表指定 index 的元素
    public void deleteAtIndex(int index) {
        if (index < 0 || index >= size) return; // 如果 index 在索引之外,直接返回
        ListNode prev = Head;
        for (int i = 0; i < index; i++) prev = prev.next; // 循环遍历,找到删除位置的前一个节点
        ListNode node = prev.next; // 拿到前一个节点,下面执行的是删除操作
        prev.next = node.next;
        node.next = null;
        size--;
    }

}

6 双指针问题 - 环形链表

这是LeetCode 的141题,题目是要找到链表中的环形,题目比较容易,比较形象的解释了双指针的移动,还有很多进阶题目,有兴趣可以去尝试做一下

6.1 题目描述

给定一个链表,判断链表中是否有环。

为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos-1,则在该链表中没有环。

在这里插入图片描述

输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。

分析题目,我们可以定义两个指针来进行移动,slow 指针每次移动一个节点,fast 指针每次移动两个节点,这样就变成了追击相遇,如果链表中有环,fast 指针最后一定会遇到 slow 指针
在这里插入图片描述

6.2 code

public class Solution {
    public boolean hasCycle(ListNode head) {
        if (head == null || head.next == null) return false;
        ListNode node = head.next;
        while (node.next != null && node.next.next != null) {
            if (node == head) return true;
            head = head.next;
            node = node.next.next;
        }
        return false;
    }
}

7 写在最后

链表这部分的代码,一定要自己去写,尤其是指针变换的部分很容易让自己绕进去,所以一定要仔细梳理一下,把知识变成自己的才可以,要加油呀~
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Geek-Banana

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值