LinkedList源码解析(手把手带你熟悉链表)

节点2.左节点 = null
节点2.右节点 = null
节点1.右节点 = 节点3
节点3.左节点 = 节点1

这样就可以断开当前节点,并且将链表重新连接起来

现在我们来实现remove(index)方法,根据索引删除指定节点:

/**

  • 删除值
    */
    public void remove(int index){
    这里代码通过索引查找节点,为了简化代码,请忽略这里的代码
    通过索引查找节点,下面会写到

    indexNode就是我们通过索引拿到的节点

indexNode = 通过索引查找节点(index)

//拿到该节点的左节点、右节点以及值
NodeBean leftNode = indexNode.leftNode;
NodeBean rightNode = indexNode.rightNode;

//判断左节点是否为空,如果为空说明当前节点为(头结点)第一个节点
if (leftNode == null) {
this.firstNode = indexNode;
}else{
//左节点不为空,需要断开自己的左节点
indexNode.leftNode = null;
//将上一个节点的右节点连接到下一个节点
leftNode.rightNode = rightNode;
}

//判断右节点是否为空,如果为空说明当前为(尾节点)最后一个节点
if (rightNode == null) {
this.lastNode = indexNode;
}else{
//右节点不为空,需要断开自己的右节点
indexNode.rightNode = null;
//将下一个节点的左节点连接到上一个节点
rightNode.leftNode = leftNode;
}

//当前节点值置空
indexNode.value = null;
size–;
}

  • 通过索引查找节点

  1. 先拿到头节点
  2. 拿到当前要查找的索引index
  3. 循环index的次数
  4. 每循环一次,就从头结点开始往后移动一个节点

现在我们来实现以下get(index)方法,通过索引获取置顶节点:

/**

  • 通过索引获取节点的值
    */
    public String get(int index){
    //由于链表没有索引,所以只能一个一个遍历查找
    //先拿到链表的第一个节点(头节点)
    NodeBean firstNode = this.firstNode;
    for (int i = 0; i < index; i++) {
    //每次循环就从头结点往后挪动一个节点
    firstNode = firstNode.rightNode;
    }
    //为了简化代码便于理解,这里不考虑tempNode为null的情况
    return firstNode.value;
    }

  • 总结

  1. 链表的每个节点之间都有连接,如果新增节点只需要直接插入就行,所以链表新增快
  2. 链表断开节点只需要将自己的前后节点重新连接就可以,所以链表删除快
  3. 链表没有索引,查找需要循环整个链表,所以查询慢
  • MyLinkedList完整代码:

public class MyLinkedList {
private int size; //当前链表的长度
private NodeBean firstNode; //头节点
private NodeBean lastNode; //尾节点

/**

  • 添加值
    */
    public void add(String value) {
    //先获取尾节点
    NodeBean lastNode = this.lastNode;
    //创建一个新节点
    NodeBean newNode = new NodeBean();
    //为节点赋值
    newNode.value = value;
    //左节点为最后一个节点(尾节点)
    newNode.leftNode = lastNode;
    //由于是添加节点,所以右节点为null,可以不写
    newNode.rightNode = null;
    //将成员变量的最后一个节点改为当前新节点
    this.lastNode = newNode;
    //判断头节点是否为空
    if (this.firstNode == null) {
    //如果为空说明当前是第一个节点,需要把头结点也设为当前节点
    this.firstNode = newNode;
    }else{
    //如果不为空,需要把前一个节点的右节点指向当前节点
    //两个节点相连接的条件是:
    // 1. 前一个节点的右节点指向当前节点
    // 2. 当前节点的左节点指向上一个节点
    lastNode.rightNode = newNode;
    }
    //链表长度+1
    size++;
    }

/**

  • 删除值
    */
    public void remove(int index){
    //先找到当前索引对应的节点
    //由于链表没有索引,所以只能一个一个遍历查找
    //先拿到链表的第一个节点(头节点)
    NodeBean indexNode = this.firstNode;
    for (int i = 0; i < index; i++) {
    //每次循环就从头结点往后挪动一个节点
    indexNode = indexNode.rightNode;
    }
    //拿到该节点的左节点、右节点以及值
    NodeBean leftNode = indexNode.leftNode;
    NodeBean rightNode = indexNode.rightNode;

//判断左节点是否为空,如果为空说明当前节点为(头结点)第一个节点
if (leftNode == null) {
this.firstNode = indexNode;
}else{
//左节点不为空,需要断开自己的左节点
indexNode.leftNode = null;
//将上一个节点的右节点连接到下一个节点
leftNode.rightNode = rightNode;
}

//判断右节点是否为空,如果为空说明当前为(尾节点)最后一个节点
if (rightNode == null) {
this.lastNode = indexNode;
}else{
//右节点不为空,需要断开自己的右节点
indexNode.rightNode = null;
//将下一个节点的左节点连接到上一个节点
rightNode.leftNode = leftNode;
}

//当前节点值置空
indexNode.value = null;
size–;
}

/**

  • 通过索引获取节点的值
    */
    public String get(int index){
    //由于链表没有索引,所以只能一个一个遍历查找
    //先拿到链表的第一个节点(头节点)
    NodeBean firstNode = this.firstNode;
    for (int i = 0; i < index; i++) {
    //每次循环就从头结点往后挪动一个节点
    firstNode = firstNode.rightNode;
    }
    //为了简化代码便于理解,这里不考虑tempNode为null的情况
    return firstNode.value;
    }

/**

  • 获取链表长度
    */
    public int getSize(){
    return this.size;
    }

/**

  • 节点实体类
    */
    private static class NodeBean {
    NodeBean leftNode; //左节点
    String value; //节点的值
    NodeBean rightNode; //右节点
    }
    }

  • 重点

  • 如果你看完上面的增删查方法, 可以完全看懂了,就可以继续往下看了

  • 如果你没看懂,请复制上面的完整代码到编辑器,自己断点研究一下

==如果上面的代码理解了,恭喜你! 现在你应该已经可以看懂官方源码了==

  • 官方代码解析

  • 节点实体类

private static class Node {
E item;
Node next;
Node prev;

Node(Node prev, E element, Node next) {
this.item = element;
this.next = next;
this.prev = prev;

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
img

总结

其实客户端开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。

Android大厂面试真题全套解析

2017-2020字节跳动Android面试真题解析PDF
然而Android架构学习进阶是一条漫长而艰苦的道路,不能靠一时激情,更不是熬几天几夜就能学好的,必须养成平时努力学习的习惯。所以:贵在坚持!

总结

其实客户端开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。

[外链图片转存中…(img-bx0Vh7gT-1711937530368)]

[外链图片转存中…(img-XyJembqi-1711937530368)]
然而Android架构学习进阶是一条漫长而艰苦的道路,不能靠一时激情,更不是熬几天几夜就能学好的,必须养成平时努力学习的习惯。所以:贵在坚持!

本文已被CODING开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》收录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值