专业汉语词典知识平台,分享汉字词语知识、历史文学知识解答!

励北网
励北网

java链表是什么,java链表结构详解

来源:小易整编  作者:小易  发布时间:2023-02-28 03:44
摘要:java链表是什么,java链表结构详解一、前言链表的历史于1955-1956年,由兰德公司的AllenNewell、CliffShaw和HerbertA.Simon开发了链表,作为他们的信息处理语言的主要数据结构。链表的另一个早期出现是由...

java链表是什么,java链表结构详解

java链表是什么,java链表结构详解

一、前言

链表的历史

于1955-1956年,由兰德公司的Allen Newell、Cliff Shaw和Herbert A. Simon开发了链表,作为他们的信息处理语言的主要数据结构。链表的另一个早期出现是由 Hans Peter Luhn 在 1953 年 1 月编写的IBM内部备忘录建议在链式哈希表中使用链表。

到 1960 年代初,链表和使用这些结构作为主要数据表示的语言的实用性已经很好地建立起来。MIT 林肯实验室的 Bert Green于 1961 年 3 月在 IRE Transactions on Human Factors in Electronics 上发表了一篇题为“用于符号操作的计算机语言”的评论文章,总结了链表方法的优点。1964 年 4 月,Bobrow 和 Raphael 的一篇评论文章“列表处理计算机语言的比较”发表在 ACM 通讯中。

二、链表数据结构

在计算机科学中,链表是数据元素的线性集合,元素的线性顺序不是由它们在内存中的物理地址给出的。它是由一组节点组成的数据结构,每个元素指向下一个元素,这些节点一起,表示线性序列。

在最简单的链表结构下,每个节点由数据和指针(存放指向下一个节点的指针)两部分组成,这种数据结构允许在迭代时有效地从序列中的任何位置插入或删除元素。

链表的数据结构通过链的连接方式,提供了可以不需要扩容空间就更高效的插入和删除元素的操作,在适合的场景下它是一种非常方便的数据结构。但在一些需要遍历、指定位置操作、或者访问任意元素下,是需要循环遍历的,这将导致时间复杂度的提升。

三、链表分类类型

链表的主要表现形式分为;单向链表、双向链表、循环链表,接下来我们分别介绍下。

1. 单向链表

单链表包含具有数据字段的节点以及指向节点行中的下一个节点的“下一个”字段。可以对单链表执行的操作包括插入、删除和遍历。

2. 双向链表

在“双向链表”中,除了下一个节点链接之外,每个节点还包含指向序列中“前一个”节点的第二个链接字段。这两个链接可以称为'forward('s')和'backwards',或'next'和'prev'('previous')。

3. 循环链表

在列表的最后一个节点中,链接字段通常包含一个空引用,一个特殊的值用于指示缺少进一步的节点。一个不太常见的约定是让它指向列表的第一个节点。在这种情况下,列表被称为“循环”或“循环链接”;否则,它被称为“开放”或“线性”。它是一个列表,其中最后一个指针指向第一个节点。

四、实现一个链表

像 Java 的源码中本身就提供了非常多的数据结构,包括我们所学习的链表 LinkedList 在日常的开发使用中也是非常频繁。

所以我们在学习的过程中,以使用 Java 程序员本身常用的语言来分析学习,并通过简化结构的方式把 LinkedList 手写实现,让读者更能方便的理解链表。

1. 链表节点

private static class Node<E> {
    E item;
    Node<E> next;
    Node<E> prev;
    
    public Node(Node<E> prev, E element, Node<E> next) {
        this.item = element;
        this.next = next;
        this.prev = prev;
    }
}
  • 链表的数据结构核心根基就在于节点对象的使用,并在节点对象中关联当前节点的上一个和下一个节点。通过这样的方式构建出链表结构。
  • 但也因为在链表上添加每个元素的时候,都需要创建新的 Node 节点,所以这也是一部分耗时的操作。

2. 头插节点

void linkFirst(E e) {
    final Node<E> f = first;
    final Node<E> newNode = new Node<>(null, e, f);
    first = newNode;
    if (f == null)
        last = newNode;
    else
        f.prev = newNode;
    size++;
}
  • 头插的操作流程,先把头节点记录下来。之后创建一个新的节点,新的节点构造函数的头节点入参为null,通过这样的方式构建出一个新的头节点。
  • 原来的头结点,设置 f.prev 连接到新的头节点,这样的就可以完成头插的操作了。另外如果原来就没有头节点,设置设置为新的节点即可。最后记录当前链表中节点的数量,也就是你使用 LinkedList 获取 size 时候就是从这个值获取的。

3. 尾插节点

void linkLast(E e) {
    final Node<E> l = last;
    final Node<E> newNode = new Node<>(l, e, null);
    last = newNode;
    if (l == null) {
        first = newNode;
    } else {
        l.next = newNode;
    }
    size++;
}
  • 尾差节点与头插节点正好相反,通过记录当前的结尾节点,创建新的节点,并把当前的结尾节点,通过 l.next 关联到新创建的节点上。同时记录 size 节点数量值。

4. 拆链操作

E unlink(Node<E> x) {
    final E element = x.item;
    final Node<E> next = x.next;
    final Node<E> prev = x.prev;
    if (prev == null) {
        first = next;
    } else {
        prev.next = next;
        x.prev = null;
    }
    if (next == null) {
        last = prev;
    } else {
        next.prev = prev;
        x.next = null;
    }
    x.item = null;
    size--;
    return element;
}
  • unlink 是一种拆链操作,只要你给定一个元素,它就可以把当前这个元素的上一个节点和一个节点进行相连,之后把自己拆除。
  • 这个方法常用语 remove 移除元素操作,因为整个操作过程不需要遍历,拆除元素后也不需要复制新的空间,所以时间复杂读为 O(1)

5. 删除节点

public boolean remove(Object o) {
    if (o == null) {
        for (Node<E> x = first; x != null; x = x.next) {
            if (x.item == null) {
                unlink(x);
                return true;
            }
        }
    } else {
        for (Node<E> x = first; x != null; x = x.next) {
            if (o.equals(x.item)) {
                unlink(x);
                return true;
            }
        }
    }
    return false;
}
  • 删除元素的过程需要 for 循环判断比删除元素的值,找到对应的元素,进行删除。
  • 循环比对的过程是一个 O(n) 的操作,删除的过程是一个 O(1) 的操作。所以如果这个链表较大,删除的元素又都是贴近结尾,那么这个循环比对的过程也是比较耗时的。

五、链表使用测试

public static void main(String[] args) {
    List<String> list = new LinkedList<>();
    // 添加元素
    list.add("a");
    list.addFirst("b");
    list.addLast("c");
    // 打印列表
    list.printLinkList();
    // 头插元素
    list.addFirst("d");
    // 删除元素
    list.remove("b");
    // 打印列表
    list.printLinkList();
}

测试结果

目前的列表,头节点:b 尾节点:c 整体:b,a,c,
目前的列表,头节点:d 尾节点:c 整体:d,a,c,
Process finished with exit code 0
  • 按照我们的测试链表对数据的操作过程,从测试结果可以看到,已经满足了链表数据结构的使用。

本文地址:百科问答频道 https://www.neebe.cn/wenda/903484.html,易企推百科一个免费的知识分享平台,本站部分文章来网络分享,本着互联网分享的精神,如有涉及到您的权益,请联系我们删除,谢谢!


百科问答
小编:小易整编
相关文章相关阅读
  • 用java开发的游戏有哪些 java架构开发的游戏推荐2023

    用java开发的游戏有哪些 java架构开发的游戏推荐2023

    java是一种非常实用的计算机语言,正因如此也把它使用在了游戏设计中,那么用java开发的游戏有哪些呢?本期小编就将带各位小伙伴了解一下相关的内容,这项有用的技术被应用到各种不同种类的游戏制作和设计中,增加了游戏的体验感,这些游戏都具有自己...

  • 如何安装java,java安装教程

    如何安装java,java安装教程

    如何安装java,java安装教程一·下载JAVA安装包并安装1.首先去官网下载JAVA安装包,JAVA安装包下载地址:https://www.oracle点com/technetwork/java/javase/downloads/ind...

  • classpath环境变量作用,Java环境变量classpath的作用

    classpath环境变量作用,Java环境变量classpath的作用

    classpath环境变量作用,Java环境变量classpath的作用环境变量环境变量(environmentvariables)一般是指在操作系统中用来指定操作系统运行环境的一些参数,如:临时文件夹位置和系统文件夹位置等。环境变量是在操...

  • 如何数组合并,JavaScript合并数组的三种方法

    如何数组合并,JavaScript合并数组的三种方法

    如何数组合并,JavaScript合并数组的三种方法数组作为一种数据结构,表示索引项的有序集合。经常会使用到数组,尤其是将多个数组进行合并,比如将数组[1,2,3]和数组[4,5,6]合并,最终得到数组[1,2,3,4,5,6]。数组的合并...

  • 怎么解析xml文件,java解析xml文件的几种方式

    怎么解析xml文件,java解析xml文件的几种方式

    怎么解析xml文件,java解析xml文件的几种方式一、为什么使用xml文件便于不同应用程序之间通信。便于不同平台之间通信。便于不同平台之间数据共享。二、读取xml的方式xml测试文件内容如下:

  • 回到顶部如何实现,JavaScript实现回到顶部功能的五种方法

    回到顶部如何实现,JavaScript实现回到顶部功能的五种方法

    回到顶部如何实现,JavaScript实现回到顶部功能的五种方法回到顶部的功能现在基本上是网页的标配了,当你已经浏览到页面底部时,一键返回顶部的功能确实非常方便。随着用户习惯的养成,这个功能都是页面必备的。那么作为一个前端开发者,我们如何实...

  • java虚拟机是什么,深入理解java虚拟机

    java虚拟机是什么,深入理解java虚拟机

    java虚拟机是什么,深入理解java虚拟机文章目录一、Java虚拟机是什么二、为什么需要了解Java虚拟机三、JavaJDK的迭代历史四、Java虚拟机发展史与种类五、Java虚拟机规范六、Java虚拟机语言无关性七、Java虚拟机的组成...

  • java入门基础知识,java入门教程【0基础自学】

    java入门基础知识,java入门教程【0基础自学】

    java入门基础知识,java入门教程源代码组织方式Java程序由package+class组成,package对应目录的相对路径,class对应文件,如E:\Workspaces\MyEclipse10\JavaStudy\src\com...

  • 周排行
  • 月排行
  • 年排行

精彩推荐