链表学习-小白也能学会的链表

针对链表内容初学者而写的博文


一、链表的概念

什么是链表?先以单向链表举例说明,单向链表像一个铁链一样相互连接,包含着多个节点(或结点),一个节点由节点中的值和指向下一个节点名为的next指针(地址)(注意:不是指向下个节点中的值)。链表中最后一个元素的next指向null。如下图所示(图中的表头我们稍后再说):
在这里插入图片描述

深入思考

观察下面两张图,他们是否都满足单链表的要求?给出理由。
第一张图:
在这里插入图片描述

第二张图:
在这里插入图片描述

解读:
第一张图片满足单链表要求,链表的一个核心是一个节点只能有一个后续节点,但是可以有多个被指向(例如第一张图的c1, c1被a2 和 b3 同时指向)
第二张图片则不满足单链表要求,因为c1有两个后续节点a5 和 b4。
另外在做题时要注意比较的是还是节点,有时候可能两个节点的值相等,但并不是同一个节点,例如下图,有两个节点的值都是1,但并不是同一个节点。
在这里插入图片描述

二、链表的相关概念

节点和头节点

在链表中,每个点都由指向下一个节点的地址组成的独立的单元,称为一个节点。
对于单链表,如果知道了第一个元素,就可以通过遍历访问整个链表,因此第一个节点最重要,一般称为头节点。(如果不知道,我们无法从头开始访问,因此注意这里说的是访问整个链表)

虚拟节点()

三、创建链表

接下来是如何构造一个链表
首先需要理解JVM是如何构建出链表的,JVM里有栈区和堆区,栈区主要存引用,也就是一个指向实际对象的地址,而堆区存的才是创建的对象,例如我们定义一个这样的类

public class Course {
    Teacher teacher;
    Student student;
}

teacherstudent是指向堆的引用,再定义:

public class Course {
	int val; //存放值
	Course next; // 存放下一个节点的地址

这里的next指向了下一个同为Course类型的对象,如图:
在这里插入图片描述
栈中的引用course(存放val(1)的地址)可以找到节点val(1),然后根据val(1)节点中存放的地址指向了val(2),以此类推直到尾节点val(5),val(5)中存放的地址为null,不再指向任何节点。

四、链表的增删改查(CRUD)

遍历链表

单链表,一定注意访问顺序!!!从头开始逐个向后访问,因此在操作之后是否能找到表头非常重要。
代码:

public static int getListLength(Node head) {
	int length = 0;
	Node node = head; // 将head节点位置给予node
	while (node != 0) {
		length++; // 说明这一节点node此时不为空 length增加
		node = node.next; // node获得下一个节点的地址
	}
	return length;
}

表头的插入

表头的插入大致分为三种

1. 在链表表头插入

此时我们有一个新节点new 我们只需要让 new.next = head即可此时new指向了head节点
易错点:忘记head重新指向表头 习惯于让head来表示头,因此让head = new即可
在这里插入图片描述
2. 在链表中间插入
在中间位置插入,先遍历链表找到插入位置,找目标节点的前一个位置,以图举例,要插入的位置在15和7之间,遍历应该在cur.next = node(7)时停止,此时cur(val) = 15。然后给newNode前后连接到链表中,注意顺序,先让newNode.next = node(15).next,然后再让node(15).next = newNode
注意:如果先让node(15).next = newNode此时没有指向node(7)的指针,因为每个节点只能有一个后续原则。
在这里插入图片描述
3. 在单链表的结尾插入节点
表尾插入就比较容易,只需要将尾节点指向新节点即可
在这里插入图片描述
插入代码实现:

public static Node insertNode(Node head, Node nodeInsert, int position) {
        //查看头节点
        if (head == null) {
            //这里可以认为待插入的节点就是链表的头节点,也可以抛出不能插入的异常
            return nodeInsert;
        }
        //获取存放的元素个数
        //查看是否越界
        int size = getLength(head);
        if (position > size + 1 || position < 1) {
            System.out.println("out range of list");
            return head;
        }

        //表头插入
        if (position == 1) {
            nodeInsert.next = head;
            head = nodeInsert;
            return head;
        }

        Node pNode = head;
        int count = 1;
        // 这里position已经被上面size限制住,不用考虑pNode == null
        while (count < position - 1) {
            // 找到插入位置前一个节点的位置
            pNode = pNode.next;
            count++;
        }
        nodeInsert.next = pNode.next;
        pNode.next = nodeInsert;
        
        return head;
    }

链表删除

删除表头节点
执行head = head.next,JVM会自动回收不可达到的节点
在这里插入图片描述
删除尾节点
删除尾节点类似于插入中间节点,都要找到目标节点的前一个节点,如果所示,让cur.next == null,此时40不再可达,会被JVM自动回收
在这里插入图片描述
删除中间节点
删除中间节点时,仍然用插入中间节点的思路,找到目标节点的前一个节点,找到位置后,让cur.next = cur.next.next即可。如图所示:
在这里插入图片描述

  • 27
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值