首页 > 编程语言 >Java链表

Java链表

时间:2023-02-22 01:11:26浏览次数:50  
标签:node index 结点 Java next 链表 size

链表

顺序表性质

  • 链表不同于顺序表,顺序表底层采用数组作为存储容器,需要分配一块连续且完整的内存空间进行使用,而链表则不需要,它通过一个指针来连接各个分散的结点,形成了一个链状的结构,每个结点存放一个元素,以及一个指向下一个结点的指针,通过这样一个一个相连,最后形成了链表。

  • 链表不需要申请连续的空间,只需要按照顺序连接即可,虽然物理上可能不相邻,但是在逻辑上依然是每个元素相邻存放的,这样的结构叫做链表(单链表)。

  • 链表分为带头结点的链表和不带头结点的链表,戴头结点的链表就是会有一个头结点指向后续的整个链表,但是头结点不存放数据:

image

  • 而不带头结点的链表就像上面那样,第一个节点就是存放数据的结点,一般设计链表都会采用带头结点的结构,因为操作更加方便。

链表的基本属性

public class LinkListt<E> 泛型E,因为表中要存的具体数据类型待定

  • 以下节点代码可以理解为就是上述图中的一个小圈/一个节点
private static class Node<E> {  //结点类,仅供内部使用
    E element;   //每个结点都存放元素
    Node<E> next;   //指向下一个结点的引用
    //因为链表一个节点需要存储值和指向下个节点(可理解就是指向另一个节点)

    public Node(E element) {//通过构造函数赋值
        this.element = element;
    }
}

private final Node<E> head = new Node<>(null);链表的头结点,用于连接之后的所有结点


链表的插入和删除

插入思路

image

image

image


删除思路

image

image

image


链表插入代码

  • if (index < 0 || index > size)判断插入的合法性
  • Node<E> prev = head;先找到对应位置的前驱结点(头节点)
  • for (int i = 0; i < index; i++)寻找到需要插入的索引号的前一位
  • Node<E> node = new Node<>(element);创建新的结点,并将需要插入的值用构造方法存储
  • node.next = prev.next;
public void add(E element, int index) {
    if (index < 0 || index > size)
        throw new IndexOutOfBoundsException("插入位置非法,合法的插入位置为:0 ~ " + size);
    Node<E> prev = head;   //先找到对应位置的前驱结点
    for (int i = 0; i < index; i++)
        prev = prev.next;
    Node<E> node = new Node<>(element);//创建新的结点,并将需要插入的值用构造方法存储
    node.next = prev.next;   //先让新的节点指向原本在这个位置上的结点
    prev.next = node;   //然后让前驱结点指向当前结点
    size++;   //完事之后一样的,更新size
}

链表删除代码

  • for (int i = 0; i < index; i++)寻找到需要插入的索引号的前一位
  • prev.next = prev.next.next; 直接将删除节点的下一位赋值会前一位的next(此时还未真的删除,因此可以使用prev.next.next)
public E remove(int index) {
    if (index < 0 || index > size - 1)   //同样的,先判断位置是否合法
        throw new IndexOutOfBoundsException("删除位置非法,合法的删除位置为:0 ~ " + (size - 1));
    Node<E> prev = head;
    for (int i = 0; i < index; i++)   //同样需要先找到前驱结点
        prev = prev.next;
    E e = prev.next.element;   //先把待删除结点存放的元素取出来
    prev.next = prev.next.next;  //可以删了
    size--;   //记得size--
    return e;
}

链表更新代码

public void setElement(int index, E e) {
    if (index < 0 || index > size - 1)
        throw new IndexOutOfBoundsException("更新位置非法,合法的删除位置为:0 ~ " + (size - 1));
    //获取指定位置的原节点
    Node<E> node = head;
    //同样需要先找到前驱结点
    for (int i = 0; i < index; i++) node = node.next;//需要到达更新节点的前一节点
    node.next.element = e;
}

链表查询代码

  • while (index-- >= 0)while循环搭配node = node.nextindex值依次递减,而节点也会依次指向下一个节点
public E getElement(int index) {
    if (index < 0 || index > size - 1)
        throw new IndexOutOfBoundsException("非法的位置,合法的位置为:0 ~ " + (size - 1));
    Node<E> node = head;
    while (index-- >= 0)   //这里直接让index减到-1为止
        node = node.next;
    return node.element;
}

链表toString

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("链表长度: ").append(getSize()).append(" ");

        Node<E> node = head.next;   //从第一个结点开始,一个一个遍历,遍历一个就拼接到字符串上去
        builder.append("链表元素: ").append(" ");
        while (node != null) {
            builder.append(node.element).append(" ");
            node = node.next;
        }
        return builder.toString();
    }
}



总代码

  • Main代码

import ClassStudy.LinkListt;

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        LinkListt<Integer> link = new LinkListt<>();
        link.add(10, 0);
        link.add(20, 1);
        link.add(30, 2);
        link.add(40, 3);
        link.add(50, 2);
        System.out.println("插入后: " + link);
        link.remove(2);
        System.out.println("删除后: " + link);
        link.setElement(0, 50);
        System.out.println("更新后: " + link);
        System.out.print("输入查询的节点位置: ");
        int index = input.nextInt();
        System.out.println("查询节点的元素: " + link.getElement(index));
    }
}

  • LinkList代码

package ClassStudy;

public class LinkListt<E> {

    private final Node<E> head = new Node<>(null);//链表的头结点,用于连接之后的所有结点
    private int size = 0;   //当前的元素数量还是要存一下,方便后面操作

    private static class Node<E> {  //结点类,仅供内部使用
        E element;   //每个结点都存放元素
        Node<E> next;   //指向下一个结点的引用

        public Node(E element) {//下一节点的元素;通过构造函数赋值
            this.element = element;
        }
    }

    //插入
    public void add(E element, int index) {
        if (index < 0 || index > size)
            throw new IndexOutOfBoundsException("插入位置非法,合法的插入位置为:0 ~ " + size);
        Node<E> prev = head;   //先找到对应位置的前驱结点
        for (int i = 0; i < index; i++)
            prev = prev.next;
        Node<E> node = new Node<>(element);   //创建新的结点
        node.next = prev.next;   //先让新的节点指向原本在这个位置上的结点
        prev.next = node;   //然后让前驱结点指向当前结点
        size++;   //完事之后一样的,更新size
    }

    //删除
    public E remove(int index) {
        if (index < 0 || index > size - 1)   //同样的,先判断位置是否合法
            throw new IndexOutOfBoundsException("删除位置非法,合法的删除位置为:0 ~ " + (size - 1));
        Node<E> prev = head;
        for (int i = 0; i < index; i++)   //同样需要先找到前驱结点
            prev = prev.next;
        E e = prev.next.element;   //先把待删除结点存放的元素取出来
        prev.next = prev.next.next;  //可以删了
        size--;   //记得size--
        return e;
    }

    //更新
    public void setElement(int index, E e) {
        if (index < 0 || index > size - 1)
            throw new IndexOutOfBoundsException("更新位置非法,合法的删除位置为:0 ~ " + (size - 1));
        //获取指定位置的原节点
        Node<E> node = head;
        //同样需要先找到前驱结点
        for (int i = 0; i < index; i++) node = node.next;//需要到达更新节点的前一节点
        node.next.element = e;
    }


    //查询
    public E getElement(int index) {
        if (index < 0 || index > size - 1)
            throw new IndexOutOfBoundsException("非法的位置,合法的位置为:0 ~ " + (size - 1));
        Node<E> node = head;
        while (index-- >= 0)   //这里直接让index减到-1为止
            node = node.next;
        return node.element;
    }

    public int getSize() {
        return size;
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("链表长度: ").append(getSize()).append(" ");

        Node<E> node = head.next;   //从第一个结点开始,一个一个遍历,遍历一个就拼接到字符串上去
        builder.append("链表元素: ").append(" ");
        while (node != null) {
            builder.append(node.element).append(" ");
            node = node.next;
        }
        return builder.toString();
    }
}

标签:node,index,结点,Java,next,链表,size
From: https://www.cnblogs.com/WoOD-outPut/p/17143034.html

相关文章

  • IDEA+java swing+MySQL配置
    1、建立一个java项目(不是空项目)2、创建GUIForm(减少代码压力)生成代码出现了这个窗体此时说明swing已经可用了3、连接MySQL......
  • 在PHP和JavaScript中设置Cookie、会话存储(SessionStorage)和本地存储(LocalStorage)
    A.Cookie介绍Cookie:Cookie常用于识别用户,它是服务器留在用户计算机中的小文件(大小限制在4KB),每当相同的计算机通过浏览器请求页面时,它会同时发送Cookie,即Cookie是随HTTP......
  • Solon v2.1.4 发布。支持 java、kotlin、groovy!
    本次发布,重点测试和验证了在java、kotlin、groovy三种jvm语言里,开箱即用的特性。并发布SolonInitializr:https://solon.noear.org/start/(也即将发布idea插件)最......
  • JavaScript相关操作
    JQUERY--HTML标签属性操作$('#id').attr('attr_name','attr_value');//设置单一属性值$('#id').attr({'attr_name1':'attr_value1','attr_name2':'attr_value2'});//......
  • Java Web(八)JSP
    JSP一.入门1.概念JavaServerPages,Java服务端页面一种动态的网页技术,其中既可以定义HTML、JS、CSS等静态内容,还可以定义Java代码的动态内容JSP=HTML+Java2.快速入门导入......
  • java代码的运行
    1. 运行流程    编译后的class文件加载到虚拟机中,加载后的Java类会被存放于方法区,运行时执行方法区内的代码。               ......
  • Java代码工具之中英文语句分词
    在自然语言处理中比较热门的操作就是中文或英文语句分词了,分词就是按照不同的算法和参数将语句分成若干词汇。拆分后的关键词可以进行词频统计或者词云图片生成等,能够快速方......
  • javaweb-filter实现登录拦击功能
    javaweb-filter实现登录拦击功能要求:用户登录了之后才能进入主页,注销的之后就不能进入主页;(在过滤器中实现!)1、用户登录页面实现前端页面代码<%@pagecontentType="text......
  • Java网络编程
    UDP和TCP网络协议,基于Socket的UDP和TCP网络编程的介绍。Author:MsuenbDate:2023-02-21网络基础知识每个计算设备上都有若干个网卡,每个网卡上有(全球唯一)单独的硬件......
  • [Java基础]自动装箱与自动拆箱--为什么整型比较必须用equals?
    偶然在项目里看到了下面这行代码,大家觉得这个if判断会存在什么问题吗?if(129==StatusEnum.OK.getCode()){//其中OK是Integercode=129System.out.println("ok");......