《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.xdnf.cn/news/1486554.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【C++中的IO流和文件操作精讲】

【本节目标】 1. C语言的输入与输出 2. 流是什么 3. CIO流 4. stringstream的简单介绍 1. C语言的输入与输出 C语言中我们用到的最频繁的输入输出方式就是scanf ()与printf()。 ⭐scanf(): 从标准输入设备(键盘)读取数据&#xff0c;并将值存放在变量中。 ⭐printf(): 将…

苹果和乔布斯的传奇故事,从车库创业到万亿市值巨头

苹果公司的品牌故事&#xff0c;就像一部充满创新、挑战与辉煌的科幻大片&#xff0c;让人目不暇接。 故事始于1976年&#xff0c;那时&#xff0c;年轻的史蒂夫乔布斯与斯蒂夫沃兹尼亚克在加州的一个简陋车库里&#xff0c;用他们的热情和智慧&#xff0c;捣鼓出了世界上第一…

【vue教程】三. 组件复用和通信(7 种方式)

目录 本章涵盖知识点回顾 组件开发与复用组件的创建和注册全局定义局部定义单文件组件&#xff08;.vue 文件&#xff09;组件的注册方式在实例中注册在 Vue 中注册 组件的 props定义 props传递 props 组件事件自定义事件的创建和触发父组件监听子组件事件父组件处理事件 Vue 实…

数字孪生:变电站监测和运维的智能化实践

随着夏季高温天气的到来&#xff0c;我国用电也迎来了高峰。用电负荷持续走高&#xff0c;对全国各地电网运维也迎来了挑战。电力系统作为现代社会的基础设施&#xff0c;其稳定性和可靠性至关重要&#xff0c;变电站则是实现电力系统电力互联互通的枢纽。 在传统变电站中&…

Python文字识别

在对于图片文字识别中&#xff0c;可以采用Python进行&#xff0c;对于下面图片&#xff1a; """ 程序实现思路&#xff1a; 1、怎么从图片中识别文字&#xff1f; 实例化OCR模型进行识别 2、怎么打开文件进行识别&#xff1f; 识别图片中的文字内容 …

SVN 服务 安装部署 Docker(compose) 方式

通过 dockerhub 或者 命令行运行 &#xff1a; docker search svn 查看 svn 的镜像 如命令行&#xff1a; [rootSGP ~]# docker search svn NAME DESCRIPTION STARS OFFICIAL AUTOMATED garethflower…

《0基础》学习Python——第十八讲__爬虫/<1>

一、什么是爬虫 爬虫是一种网络数据抓取的技术。通过编写程序&#xff08;通常使用Python&#xff09;&#xff0c;爬虫可以自动化地访问网页&#xff0c;解析网页内容并提取出所需的数据。爬虫可以用于各种用途&#xff0c;如搜索引擎的索引&#xff0c;数据分析和挖掘&#x…

系统编程--Linux下文件的“其他操作”函数

这里写目录标题 文件存储理论补充dentry、inode 文件其他操作stat函数作用函数原型代码&#xff08;以获取文件大小为例&#xff09;补充&#xff08;获取文件类型&#xff09; lstat函数作用函数原型代码补充&#xff08;获取文件权限&#xff09;总结 tipslink函数作用简介函…

有哪些好用的 AI 学术研究工具和科研工具?

AI视频生成&#xff1a;小说文案智能分镜智能识别角色和场景批量Ai绘图自动配音添加音乐一键合成视频百万播放量https://aitools.jurilu.com/ AI 应用其实分两个层面&#xff0c;第一是模型&#xff0c;第二是应用。现在很多模型厂家都是既做 toC 的对话应用&#xff0c;也做 t…

使用API有效率地管理Dynadot域名,处理域名推送请求

简介 Dynadot是通过ICANN认证的域名注册商&#xff0c;自2002年成立以来&#xff0c;服务于全球108个国家和地区的客户&#xff0c;为数以万计的客户提供简洁&#xff0c;优惠&#xff0c;安全的域名注册以及管理服务。 Dynadot平台操作教程索引&#xff08;包括域名邮箱&…

Nginx学习-相关概念

Nginx学习-相关概念 主要学习几个概念&#xff1a;Nginx&#xff0c;正向代理、反向代理、负载均衡、动静分离。–2020年05月29日 什么是Nginx Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器&#xff0c;同时也提供了IMAP/POP3/SMTP服务。 特点是占有内存少&…

绘制混淆矩阵热力图

Python绘制混淆矩阵热力图 用matplotlib绘制混淆矩阵&#xff0c;可以通过改变 imshow 函数中的 cmap 参数来修改颜色。cmap 参数接受一个 colormap 的名字&#xff0c;你可以选择许多不同的 colormap&#xff0c;例如 ‘viridis’, ‘plasma’, ‘inferno’, ‘magma’, ‘civ…

Rust代码答疑报错|Python一对一辅导答疑

Question 你好&#xff0c;我是悦创。 学员答疑&#xff1a; https://code.bornforthis.cn/?id4e72084d-1eaf-44ed-8067-744671491574https://code.bornforthis.cn/?id664ff169-41d6-409f-a05b-02ed42279759 问题代码&#xff1a; // You can bring module paths into sc…

阶梯-度小满春招算法方向第1批

问题的题面是典型的最长上升子序列问题。求方案数属动态规划问题&#xff0c;可推出以a[i]为最大节点的上升子序列方案数公式 dp[i]{dp[j] , 1<j<i-1&&f[j]1f[i]} &#xff08;f为最大上升子序列&#xff09;。 并且这个方案总数不会超过n&#xff0c;因此也…

C++相关概念和易错语法(24)(map、迭代器分类)

1.map 在上篇文章中&#xff0c;我着重介绍了set&#xff0c;由于map和set同源&#xff0c;所以这次我会着重介绍map别于set的地方 &#xff08;1&#xff09;模板参数 set是以单一的key作为成员变量&#xff0c;而map是以pair作为成员变量&#xff0c;而pair的first作为key来…

mysql对数据库的增删改

目录 DML语句&#xff1a; 增加数据&#xff08;insert语句&#xff09; 增加数据&#xff08;insert into select&#xff09; 修改数据&#xff08;update语句&#xff09; 【where 子句条件】 删除数据&#xff08;delete语句&#xff09; 删除数据&#xff08;trunca…

【北京迅为】《i.MX8MM嵌入式Linux开发指南》-第三篇 嵌入式Linux驱动开发篇-第四十一章 物理地址与虚拟地址

i.MX8MM处理器采用了先进的14LPCFinFET工艺&#xff0c;提供更快的速度和更高的电源效率;四核Cortex-A53&#xff0c;单核Cortex-M4&#xff0c;多达五个内核 &#xff0c;主频高达1.8GHz&#xff0c;2G DDR4内存、8G EMMC存储。千兆工业级以太网、MIPI-DSI、USB HOST、WIFI/BT…

C# 委托函数 delegate

在C#中&#xff0c;委托&#xff08;Delegate&#xff09;是一种特殊的类型&#xff0c;它可以持有对方法的引用。 委托是实现事件的基础。事件本质上是多播委托&#xff0c;允许多个方法被触发 委托允许你将方法作为参数传递给其他方法&#xff0c;或者将方法作为返回值从方法…

基于生物地理算法的MLP多层感知机优化matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 4.1 生物地理算法&#xff08;BBO&#xff09;原理 4.2 多层感知机&#xff08;MLP&#xff09; 4.3 BBO优化MLP参数 5.完整程序 1.程序功能描述 基于生物地理算法的MLP多层感知机优化mat…

昇思25天学习打卡营第23天|ShuffleNet图像分类

ShuffleNet网络介绍 ShuffleNetV1是旷视科技提出的一种计算高效的CNN模型&#xff0c;和MobileNet, SqueezeNet等一样主要应用在移动端&#xff0c;所以模型的设计目标就是利用有限的计算资源来达到最好的模型精度。ShuffleNetV1的设计核心是引入了两种操作&#xff1a;Pointw…