算法通关村第一关——链表青铜挑战笔记

链表是一种基本的数据结构,通过指针连接各个元素。在JVM中,栈区存储引用,堆区存储对象。文章介绍了如何构建链表,包括单链表的定义和表示,并提供了添加、删除节点的算法实现。链表的操作通常从头节点开始,需要遍历以访问或修改元素。
摘要由CSDN通过智能技术生成

什么是链表?

链表是一种最基本的结构,普通的单链表就是只给你一个指向链表头的指针head,如果想访问其他元素,就只能从head开始一个个向后找,遍历链表最终会在访问尾结点之后如果继续访问,就会返回null。

怎么理解链表的构建

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

/**
 * 在算法中最常用的链表定义方式
 */
public class Teacher {
    public int age;
    public Teacher val;

    public Teacher(int age) {
        this.age = age;
        this.val = null;
    }

    public static void main(String[] args) {
        Teachere teacher1=new Teacher(11);
        Teachere teacher2=new Teacher(12);//这个其实就是在teacher1建立了连接teacher2的关系
    }
}

等同于的关系:

/**
 * 在算法中最常用的链表定义方式
 */
public class ListNode {
    public int val;
    public ListNode next;

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

    public static void main(String[] args) {
        ListNode listnode=new ListNode(1);
    }
}

jvm中的关系图如下:

这就是一个简单的线性访问了,所以链表就是从head开始,逐个开始向后访问,而每次所访问对象的类型都是一样的。根据面向对象的理论,在Java里规范的链表应该这么定义:

public class ListNode {
    private int data;
    private ListNode next;
    public ListNode(int data) {
        this.data = data;
    }
    public int getData() {
        return data;
    }
    public void setData(int data) {
        this.data = data;
    }
    public ListNode getNext() {
        return next;
    }
    public void setNext(ListNode next) {
        this.next = next;
    }
}

增删改查

算法的基础是数据结构,任何数据结构的基础都是创建+增删改查,由这几个操作可以构造很多算法题,所以我们也从这五项开始学习链表。

链表的遍历

对于单链表,不管进行什么操作,一定是从头开始逐个向后访问,所以操作之后是否还能找到表头非常重要。

image.png

 实现代码如下:

public static int getListLength(Node head) {
        int length = 0;
       Node node = head;
        while (node != null) {
            length++;
            node = node.next;
        }
        return length;
    }

添加节点

如图所示:

链表-添加节点

/**
     * 链表插入
     * @param head       链表头节点
     * @param nodeInsert 待插入节点
     * @param position   待插入位置,从1开始
     * @return 插入后得到的链表头节点
     */
    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("位置参数越界");
            return head;
        }

        //表头插入
        if (position == 1) {
            nodeInsert.next = head;
            // 这里可以直接 return nodeInsert;还可以这么写:
            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;
    }

 删除节点

链表-删除节点

代码如下:

/**
     * 删除节点
     * @param head     链表头节点
     * @param position 删除节点位置,取值从1开始
     * @return 删除后的链表头节点
     */
    public static Node deleteNode(Node head, int position) {
        if (head == null) {
            return null;
        }
        int size = getListLength(head);
        //思考一下,这里为什么是size,而不是size+1
        if (position > size || position <1) {
            System.out.println("输入的参数有误");
            return head;
        }
        if (position == 1) {
            //curNode就是链表的新head
            return head.next;
        } else {
            Node preNode = head;
            int count = 1;
            while (count < position - 1) {
                preNode = preNode.next;
                count++;
            }
            Node curNode = preNode.next;
            preNode.next = curNode.next;
        }
        return head;
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值