《Java初阶数据结构》----3.<线性表---LinkedList与链表>

目录

前言

一、链表的简介

1.1链表的概念

1.2链表的八种结构 

重点掌握两种

1.3单链表的常见方法

三、单链表的模拟实现

四、LinkedList的模拟实现(双链表)

4.1 什么是LinkedList

4.2LinkedList的使用

五、ArrayList和LinkedList的区别 


前言

      大家好,我目前在学习java。之前也学了一段时间,但是没有发布博客。时间过的真的很快。我会利用好这个暑假,来复习之前学过的内容,并整理好之前写过的博客进行发布。如果博客中有错误或者没有读懂的地方。热烈欢迎大家在评论区进行讨论!!!

      喜欢我文章的兄弟姐妹们可以点赞,收藏和评论我的文章。喜欢我的兄弟姐妹们以及也想复习一遍java知识的兄弟姐妹们可以关注我呦,我会持续更新滴,
     望支持!!!!!!一起加油呀!!!!

语言只是工具,不能决定你好不好找工作,决定你好不好找工作的是你的能力!!!!!

学历本科及以上就够用了!!!!!!!!!!!!!!!!!!


本篇博客主要讲解Java基础语法中的

一、链表的简介

1.1链表的概念

1.2链表的八种结构

重点掌握两种结构:

1.3单链表的常见方法

三、单链表的模拟实现

四、LinkedList的模拟实现(双链表)

4.1 什么是LinkedList

4.2LinkedList的使用(及实现)

五、ArrayList和LinkedList的区别

一、链表的简介

1.1链表的概念

链表是一种物理存储结构上非连续存储结构,数据元素的逻辑顺序是通过链表中的引用链接次序实现的 。

1.2链表的八种结构 

下面三种情况组合起来就有八种2^3。

1. 单向或者双向 

2.带头或者不带头

3. 循环或者非循环

重点掌握两种

1.无头单向非循环链表(单链表):结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。另外这种结构在笔试面试中出现很多。

2.无头双向链表(双链表):在Java的集合框架库中LinkedList底层实现就是无头双向循环链表。

1.3单链表的常见方法

 // 1、无头单向非循环链表实现public class SingleLinkedList {//头插法public void addFirst(int data){}//尾插法public void addLast(int data){}//任意位置插入,第一个数据节点为0号下标public void addIndex(int index,int data){}//查找是否包含关键字key是否在单链表当中public boolean contains(int key){return false;}//删除第一次出现关键字为key的节点public void remove(int key){}//删除所有值为key的节点public void removeAllKey(int key){}//得到单链表的长度public int size(){return -1;}public void clear() {}public void display() {}}

三、单链表的模拟实现

用内部类的方式定义链表节点。

    //链表是由每一个节点组成的,每一个节点都是一个对象,
//  如果我们去抽象他,它有两个域,节点是链表的一部分,所以我们把节点定义成内部类static class ListNode{public int val;//节点的值域,整型public ListNode next;//下一个节点的地址,要表示节点的地址,因此是ListNode类型//由于new新的节点对象时,值可以知道,但是下一个节点的地址是未知的//因此我们创建构造方法时,只初始化val的值,next的值默认为null。public ListNode(int val) {this.val = val;}}

 再定义一个头结点

    //对于链表本身,还应该有个head,来表示当前链表的头结点,这是我们链表的头结点//而不是节点的头结点。因此是链表的属性,切勿放到节点类之中。节点类只有两个属性,值域和下一个节点的地址域//要表示节点的地址,因此是ListNode类型public ListNode head;

简单的初始化链表 

    public void easyCreateList(){ListNode node1 = new ListNode(12);ListNode node2 = new ListNode(23);ListNode node3 = new ListNode(34);ListNode node4 = new ListNode(45);ListNode node5 = new ListNode(56);node1.next = node2;node2.next = node3;node3.next = node4;node4.next = node5;this.head = node1;}

遍历打印链表 

    //注意:head必须一直指向第一个节点的位置,从而来找到这个链表//因此我们定义一个ListNode类型的cur。public void display(){ListNode cur = head;if (cur == null){System.out.print("当前链表为空,无法打印");}while (cur != null){System.out.printf(cur.val+" ");cur = cur.next;}System.out.println();}

从某节点开始打印链表 

    public void display(ListNode listNode){ListNode cur = listNode;if (cur == null){System.out.print("当前链表为空,无法打印");}while (cur != null){System.out.printf(cur.val+" ");cur = cur.next;}System.out.println();}

 求链表的长度

    //求链表的长度public int size(){int count = 0;ListNode cur = head;while (cur != null){count++;cur = cur.next;}return count;}

 是否链表是否包含关键字key

    //是否链表是否包含关键字keypublic boolean contains(int key){ListNode cur = head;while (cur != null){if(key == cur.val){return true;}cur = cur.next;}return false;}

头插法 

    //头插法,就算链表里一个节点都没有,此方法也可以插入新的节点//因此创建链表可以用此方法创建public void addFirst(int data){ListNode node = new ListNode(data);node.next = head;head = node;}

尾插法

    //尾插法,在链表最后面插入元素public void addLast(int data){ListNode node = new ListNode(data);ListNode cur = head;if (cur == null){head = node;return;}//找到链表的尾节点while (cur.next != null){cur = cur.next;}cur.next = node;}

在指定位置插入元素

    //在指定位置插入元素public void addIndex(int index, int data){if(index < 0|| index > size()){System.out.println("index不合法");return;}if(index == 0){addFirst(data);return;}if(index == size()){addLast(data);return;}
//        ListNode node = new ListNode(data);
//        ListNode pre = head;
//        int count = 0;
//        while (true){
//            pre = pre.next;
//            count++;
//            if (index == count+1){
//                node.next = pre.next;
//                pre.next = node;
//                break;
//            }
//        }ListNode cur = findIndexSubOne(index);ListNode node = new ListNode(data);node.next = cur.next;cur.next = node;}

 找到要删除节点的位置的前一个节点

    //找到要删除节点的位置的前一个节点private ListNode findIndexSubOne(int index){ListNode cur = head;for (int i = 0; i<index-1; i++){cur = cur.next;}return cur;//        while (index-1 != 0){
//            cur = cur.next;
//            index--;
//        }
//        return cur;}

 删除第一次出现关键字为key的节点

    //删除第一次出现关键字为key的节点public void remove(int key){if(head == null){System.out.println("当前链表为空,您要删除的数据不存在");return;}if (head.val == key){head = head.next;return;}ListNode cur = searchPrev(key);if (cur == null){System.out.println("没有找到你要删除的数字");return;}cur.next = cur.next.next;}

找到key的前驱

    //找到key的前驱private ListNode searchPrev(int key){ListNode cur = head;while (cur.next!=null){if (cur.next.val == key){return cur;}cur = cur.next;}return null;}

 删除链表中元素

    public void removeAllKey(int key){if(head == null){System.out.println("当前链表为空,无法删除!");return;}ListNode cur = head.next;ListNode prev = head;while (cur != null){if(cur.val == key){prev.next = cur.next;cur = cur.next;}else {cur = cur.next;prev = prev.next;}}if (head.val == key){head = head.next;}}

逆置链表 

    public ListNode reverseList(ListNode head){if(head == null){return null;}if(head.next == null){return head;}ListNode cur = head.next;head.next = null;while (cur != null){ListNode curNext = cur.next;cur.next = head;head = cur;cur = curNext;}return head;}

    public void reverseList(){if(head == null){return;}if(head.next == null){return;}ListNode cur = head.next;head.next = null;while (cur != null){ListNode curNext = cur.next;cur.next = head;head = cur;cur = curNext;}}

 用栈的方式逆序打印链表

    //用栈的方式逆序打印链表public void reverseStackList(){Stack<ListNode> stack = new Stack<>();ListNode cur = head;while (cur != null){stack.push(cur);cur=cur.next;}while (!stack.isEmpty()){ListNode top = stack.pop();System.out.print(top.val+" ");}System.out.println();}

暴力清空链表 

    public void clear(){this.head = null;}

四、LinkedList的模拟实现(双链表)

4.1 什么是LinkedList

LinkedList:的底层是双向链表结构,由于链表没有将元素存储在连续的空间中,元素存储在单独的节 点中,然后通过引用将节点连接起来了,因此在在任意位置插入或者删除元素时,不需要搬移元素,效率比较高。

在集合框架中,LinkedList也实现了List接口,具体如下:

说明

1. LinkedList实现了List接口

2. LinkedList的底层使用了双向链表

3. LinkedList没有实现RandomAccess接口,因此LinkedList不支持随机访问

4. LinkedList的任意位置插入和删除元素时效率比较高,时间复杂度为O(1)

5. LinkedList比较适合任意位置插入的场景

4.2LinkedList的使用(及实现)

 1. LinkedList的构造

2. LinkedList的其他常用方法介绍 

3.方法的具体实现 

使用内部类构造双链表的节点,头节点,尾结点 

    static class ListNode{private int val;//链表值域private ListNode prev;//前节点地址private ListNode next;//后节点地址//构造方法,初始化链表节点值域public ListNode(int val) {this.val = val;}}public ListNode head; //双向链表的头结点public ListNode last;//双向链表的尾巴

头插法

    //头插法public void addFirst(int data){ListNode node = new ListNode(data);if (head == null){head = node;last = node;return;}head.prev =node;node.next = head;head = node;}

尾插法

    //尾插法public void addLast(int data){ListNode node =new ListNode(data);if (head == null){head = node;last = node;return;}last.next =node;node.prev = last;last = node;}

链表长度

    //链表长度public int size(){int count = 0;ListNode cur = head;while (cur != null){cur = cur.next;count++;}return count;}

 打印链表

    //打印链表public void display(){ListNode cur = head;if (cur == null){System.out.println("该链表为空,无法打印!");return;}while (cur != null){System.out.print(cur.val+" ");cur = cur.next;}System.out.println();//方便测试看数据}

链表是否包含某元素

    //链表是否包含某元素public boolean contains(int key){ListNode cur = head;if (cur == null){System.out.println("该链表为空!");return false;}while (cur != null){if(cur.val == key){return true;}cur = cur.next;}return false;}

检查下标是否异常

    //检查下标是否异常public void checkIndex(int index){if (index<0 || index >size()){//等于size用尾插法throw new indexOutOfException("index 不合法!"+index);}}

 在某位置添加元素

    public void addIndex(int index, int data) {checkIndex(index);if (index == 0) {addFirst(data);return;}if(index == size()) {addLast(data);return;}ListNode node = new ListNode(data);
//            while (index !=0){
//                cur = cur.next;
//                index--;
//            }ListNode cur = searchIndexNode(index);node.prev=cur.prev;node.next=cur;cur.prev.next = node;cur.prev = node;}

 找到第n个节点的位置

    //双链表,由于知道了前一个节点的位置//因此插进第n个元素时直接找到第n个节点的位置就可以private ListNode searchIndexNode(int index){ListNode cur =head;while (index !=0){cur = cur.next;index--;}return cur;}

 删除第一个出现的某元素

删除链表中所有这个元素

 后续会添加完整的代码

五、ArrayList和LinkedList的区别 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/876111.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

机器学习(五) -- 无监督学习(1) --聚类1

系列文章目录及链接 上篇&#xff1a;机器学习&#xff08;五&#xff09; -- 监督学习&#xff08;7&#xff09; --SVM2 下篇&#xff1a;机器学习&#xff08;五&#xff09; -- 无监督学习&#xff08;1&#xff09; --聚类2 前言 tips&#xff1a;标题前有“***”的内容…

Python 教程(四):Python运算符合集

目录 专栏列表前言1. 算术运算符2. 比较运算符3. 逻辑运算符4. 位运算符5. 赋值运算符6. 成员运算符7. 身份运算符总结 在前三篇教程中&#xff0c;我们学习了 Python 的基本语法和数据结构以及字符串的特性。本篇教程&#xff0c;我们将深入探讨 Python 中的运算符合集。 专栏…

transformers进行学习率调整lr_scheduler(warmup)

一、get_scheduler实现warmup 1、warmup基本思想 Warmup&#xff08;预热&#xff09;是深度学习训练中的一种技巧&#xff0c;旨在逐步增加学习率以稳定训练过程&#xff0c;特别是在训练的早期阶段。它主要用于防止在训练初期因学习率过大导致的模型参数剧烈波动或不稳定。…

搜维尔科技:Patchwork 3D-提高汽车设计的效率和创造力

提高汽车设计的效率和创造力 我们很高兴地宣布推出专为雷诺3DCommerce设计的突破性Blender插件。这款创新工具简化了将车辆配置从Patchwork 3D直接导入领先的免费 3D 建模软件Blender的过程。这款插件彰显了我们致力于提供定制解决方案以满足业务需求的承诺。 主要优点&#x…

使用图数据库Nebula Graph快速上手史上最大规模的中文知识图谱ownthink_v2教程(没写完,明天再写)

一、前言 本教程主要参考官方教程&#xff1a;使用图数据库 Nebula Graph 数据导入快速体验知识图谱 OwnThink (nebula-graph.com.cn) 来带着大家一步一步复现实验内容。 本教程主要使用到的数据集&#xff1a; ownthink/KnowledgeGraphData: 史上最大规模1.4亿中文知识图谱…

python | gunicorn,一个非常实用的 Python 库!

本文来源公众号“python”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;gunicorn&#xff0c;一个非常实用的 Python 库&#xff01; 大家好&#xff0c;今天为大家分享一个非常实用的 Python 库 - gunicorn。 Github地址&…

photoshop学习笔记——选区3 快速选择工具

快速选择工具 W shift W 在3种快速选择工具之间切换 对象选择工具 photoshop CC中没有这个工具&#xff0c;利用AI&#xff0c;将款选中的对象快速的提取选区&#xff0c;测试了一下&#xff0c;选区制作的非常nice快速选择工具 跟磁性套索类似&#xff0c;自动识别颜色相似…

Rust编程- 函数指针与返回闭包

函数指针 &#xff1a; 可以将普通函数传递至其他函数。函数会在传递的过程中被强制转换成fn类型&#xff0c;区别闭包的Fn fn类型也就是所谓的函数指针&#xff08;function pointer&#xff09; fn add_one(x:i32) ->i32{x 1 }fn do_twice(f:fn(i32)-> i32,arg:i32) …

100条牛批的MySql Sql语句排行榜

目录 一、基本查询 1.1 选择所有记录&#xff1a; 1.2 选择特定列&#xff1a; 1.3 过滤记录&#xff1a; 1.4 排序记录&#xff1a; 1.5 限制记录数&#xff1a; 1.6 统计记录数&#xff1a; 1.7 求和&#xff1a; 1.8 平均值&#xff1a; 1.9 最大值&#xff1a; …

02 Redis安装与启动

Redis安装与启动 一、Redis安装与启动 一&#xff09;Redis的安装 ​ 大多数企业都是基于Linux服务器来部署项目&#xff0c;而且Redis官方也没有提供Windows版本的安装包。 1.源码包 ​ github下载链接&#xff08;可选择6.x版本&#xff09;&#xff1a;Releases redis…

ClkLog:开源用户行为分析框架,让数据分析更轻松

ClkLog&#xff1a;开源用户行为分析框架&#xff0c;让数据分析更轻松 在数据驱动的时代&#xff0c;找到一个好用的用户行为分析工具真是难上加难。但是今天你有福了&#xff0c;开源免费的 ClkLog 就是你的不二选择&#xff01;本文将为你详细介绍 ClkLog 的功能特点、技术架…

Spark RPC框架详解

文章目录 前言Spark RPC模型概述RpcEndpointRpcEndpointRefRpcEnv 基于Netty的RPC实现NettyRpcEndpointRefNettyRpcEnv消息的发送消息的接收RpcEndpointRef的构造方式直接通过RpcEndpoint构造RpcEndpointRef通过消息发送RpcEndpointRef Endpoint的注册Dispatcher消息的投递消息…

聚焦民生服务 助力企业发展 区块链应用加速落地

聚焦民生服务&#xff0c;助力企业发展&#xff0c;区块链应用正在加速落地。这一趋势体现了区块链技术在多个领域的广泛应用和深远影响。以下是对这一主题的详细分析&#xff1a; 一、区块链在民生服务中的应用 政务服务 数据共享与打通&#xff1a;区块链技术利用其分布式账…

Python酷库之旅-第三方库Pandas(048)

目录 一、用法精讲 171、pandas.Series.nlargest方法 171-1、语法 171-2、参数 171-3、功能 171-4、返回值 171-5、说明 171-6、用法 171-6-1、数据准备 171-6-2、代码示例 171-6-3、结果输出 172、pandas.Series.nsmallest方法 172-1、语法 172-2、参数 172-3、…

自动化测试 - selenium 环境搭建

在进行自动化测试时&#xff0c;Selenium 是一个非常强大的工具&#xff0c;在使用前需要做一些环境准备。 1. 配置 Chromedriver 访问 Chrome 浏览器的官方网站&#xff08;https://www.google.cn/chrome/&#xff09;&#xff0c;下载并安装 Chrome 浏览器。 接下来&#x…

html必知必会-html内嵌JavaScript和文件路径

文章目录 HTML JavaScriptHTML <script> 标签JavaScript 的简单示例HTML <noscript> 标签HTML 文件路径绝对文件路径相对文件路径总结 HTML JavaScript JavaScript 使 HTML 页面更具动态性和交互性。 示例 <!DOCTYPE html> <html> <body><…

leetcode9 -- 回文数

题目描述&#xff1a; 给你一个整数 x &#xff0c;如果 x 是一个回文整数&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 回文数 是指正序&#xff08;从左向右&#xff09;和倒序&#xff08;从右向左&#xff09;读都是一样的整数。 例如&#xff0c;…

vue3前端开发-小兔鲜项目-路由缓存的更新解决办法

vue3前端开发-小兔鲜项目-路由缓存的更新解决办法&#xff01;默认情况下&#xff0c;如果我们不想办法解决这个问题&#xff0c;vue3框架有个默认的约定&#xff0c;那就是&#xff0c;当仅仅是路由参数发生变化的时候&#xff0c;框架并不会更新整个模块的内容。但是我们现在…

自训练和增量训练word2vec模型

1、自己准备训练语料文件 根据自己的业务场景准备训练数据&#xff0c;比如用户在商城上的同购行为序列或同浏览行为序列。 我们希望通过自己训练业务相关的语料word2vec模型来获得词嵌入、词相关性查询等。 1.1 准备语料库文件 # 示例&#xff1a;准备自己的一个大规模的语…

RDMA通信4:MR(Memory Region, 内存区域)基本概念和作用

MR简介 RDMA通信中MR(Memory Region)指的是由RDMA软件层在内存中规划出的一片区域&#xff0c;用于存放收发的数据。IB协议中&#xff0c;用户在申请完用于存放数据的内存区域之后&#xff0c;都需要通过调用IB框架提供的API注册MR&#xff0c;才能让RDMA网卡访问这片内存区域…