java的LinkedList

java的LinkedList

  • 什么是LinkedList
  • LinkedList的模拟实现
  • LinkedList的使用
  • ArrayList和LinkedList的区别

什么是LinkedList

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

  1. LinkedList实现了List接口
  2. LinkedList的底层使用了双向链表
  3. LinkedList没有实现RandomAccess接口,因此LinkedList不支持随机访问
  4. LinkedList的任意位置插入和删除元素时效率比较高,时间复杂度为O(1)
  5. LinkedList比较适合任意位置插入的场景

LinkedList的模拟实现

在这里插入图片描述

public interface IList {//头插法public void addFirst(int data);//尾插法public void addLast(int data);//任意位置插入,第一个数据节点为0号下标public void addIndex(int index,int data);//查找是否包含关键字key是否在双向链表当中public boolean contains(int key);//删除第一次出现关键字为key的节点public void remove(int key);//删除所有值为key的节点public void removeAllKey(int key);//得到双向链表的长度public int size();public void clear();public void display();
}
public class MyLinkedList implements IList{static class ListNode{public int val;public ListNode prev;public ListNode next;public ListNode(int val) {this.val = val;}}public ListNode head;public ListNode last;@Overridepublic void addFirst(int data) {}@Overridepublic void addLast(int data) {}@Overridepublic void addIndex(int index, int data) {}@Overridepublic boolean contains(int key) {return false;}@Overridepublic void remove(int key) {}@Overridepublic void removeAllKey(int key) {}@Overridepublic int size() {return 0;}@Overridepublic void clear() {}@Overridepublic void display() {}}

我们先来实现打印链表和得到链表长度

@Override
public int size() {ListNode cur = this.head;int count = 0;while(cur != null){cur = cur.next;count++;}return count;
}
@Override
public void display() {ListNode cur = this.head;while(cur != null){System.out.print(cur.val + " ");cur = cur.next;}System.out.println();
}

接下来实现头插法

在这里插入图片描述

@Override
public void addFirst(int data) {ListNode newNode = new ListNode(data);if(this.head == null){head = last = newNode;return;}head.prev = newNode;newNode.next = head;head = newNode;
}
public class Test {public static void main(String[] args) {MyLinkedList list = new MyLinkedList();list.addFirst(56);list.addFirst(45);list.addFirst(34);list.addFirst(23);list.addFirst(12);list.display();list.addFirst(33);list.display();System.out.println(list.size());}//结果为://12 23 34 45 56 //33 12 23 34 45 56 //6
}

实现尾插法
在这里插入图片描述

@Override
public void addLast(int data) {ListNode newNode = new ListNode(data);if(head == null){head = last = newNode;return;}last.next = newNode;newNode.prev = last;;last = newNode;
}
public class Test {public static void main(String[] args) {MyLinkedList list = new MyLinkedList();list.addLast(12);list.addLast(23);list.addLast(34);list.addLast(45);list.addLast(56);list.display();}//结果为://12 23 34 45 56
}

实现任意位置插入,第一个数据节点为0号下标
在这里插入图片描述

private ListNode findIndex(int index){ListNode cur = this.head;while(index != 0){cur = cur.next;index--;}return cur;
}
@Override
public void addIndex(int index, int data) {int len = size();if(index < 0 || index > len - 1){return;}if(index == 0){addFirst(data);return;}if(index == len - 1){addLast(data);return;}ListNode cur = findIndex(index);ListNode newNode = new ListNode(data);newNode.next = cur;cur.prev.next = newNode;newNode.prev = cur.prev;cur.prev = newNode;
}
public class Test {public static void main(String[] args) {MyLinkedList list = new MyLinkedList();list.addLast(12);list.addLast(23);list.addLast(34);list.addLast(45);list.addLast(56);list.display();list.addIndex(2,33);list.display();list.addIndex(0,33);list.display();list.addIndex(6,33);list.display();list.addIndex(8,33);list.display();}//结果为://12 23 34 45 56//12 23 33 34 45 56//33 12 23 33 34 45 56//33 12 23 33 34 45 56 33//33 12 23 33 34 45 56 33
}

实现删除第一次出现关键字为key的节点
在这里插入图片描述

@Override
public void remove(int key) {ListNode cur = this.head;while(cur != null){if(cur.val == key){if(cur == this.head){head = head.next;if(head != null){head.prev = null;}}else{cur.prev.next = cur.next;if(cur.next == null){last = last.prev;}else{cur.next.prev = cur.prev;}}return;}cur = cur.next;}
}
public class Test {public static void main(String[] args) {MyLinkedList list = new MyLinkedList();list.addLast(12);list.addLast(23);list.addLast(34);list.addLast(45);list.addLast(56);list.display();list.remove(12);list.display();list.remove(56);list.display();list.remove(34);list.display();}//结果为://12 23 34 45 56//23 34 45 56//23 34 45//23 45
}

删除所有值为key的节点,我们只需要在删除第一次出现关键字为key的节点的代码上将return删除掉,让其循环到链表结尾

@Override
public void removeAllKey(int key) {ListNode cur = this.head;while(cur != null){if(cur.val == key){if(cur == this.head){head = head.next;if(head != null){head.prev = null;}}else{cur.prev.next = cur.next;if(cur.next == null){last = last.prev;}else{cur.next.prev = cur.prev;}}}cur = cur.next;}
}
public class Test {public static void main(String[] args) {MyLinkedList list = new MyLinkedList();list.addLast(23);list.addLast(33);list.addLast(34);list.addLast(23);list.addLast(23);list.display();list.removeAllKey(23);list.display();}//结果为://23 33 34 23 23//33 34
}

实现查找是否包含关键字key是否在双向链表当中,我们只需要遍历链表,找到返回true,没找到返回false

@Override
public boolean contains(int key) {ListNode cur = this.head;while(cur != null){if(cur.val == key){return true;}cur = cur.next;}return false;
}
public class Test {public static void main(String[] args) {MyLinkedList list = new MyLinkedList();list.addLast(12);list.addLast(23);list.addLast(34);list.addLast(45);list.addLast(56);list.display();System.out.println(list.contains(34));System.out.println(list.contains(100));}//结果为://12 23 34 45 56//true//false
}

接下来实现clear,我们可以直接暴力的将head和last置为null
但是最后是将每个结点的prev和last都置为null,我们需要一个curN保留下一个结点,最后还需要将head和last置为null

@Override
public void clear() {ListNode cur = this.head;while(cur != null){ListNode curN = cur.next;cur.prev = null;cur.next = null;cur = curN;}this.head = this.last = null;
}
public class Test {public static void main(String[] args) {MyLinkedList list = new MyLinkedList();list.addLast(12);list.addLast(23);list.addLast(34);list.addLast(45);list.addLast(56);list.display();list.clear();list.display();}//结果为://12 23 34 45 56//
}

LinkedList的使用

  1. LinkedList的构造
方法解释
LinkedList ()无参构造
LinkedList (Collection<? extends E> c)利用其他集合容器中元素构造List
import java.util.ArrayList;
import java.util.LinkedList;
public class Test {public static void main(String[] args) {//构造一个空的LinkedListLinkedList<Integer> list1 = new LinkedList<>();list1.add(1);list1.add(2);list1.add(3);list1.add(4);list1.add(5);System.out.println(list1);ArrayList<Integer> list2 = new ArrayList<>();list2.add(11);list2.add(22);list2.add(33);list2.add(44);list2.add(55);//使用ArrayList构造LinkedListLinkedList<Integer> list3 = new LinkedList<>(list2);System.out.println(list3);}//结果为://[1, 2, 3, 4, 5]//[11, 22, 33, 44, 55]
}
  1. LinkedList的其他常用方法介绍
方法解释
boolean add(E e)尾插 e
void add(int index, E element)将 e 插入到 index 位置
boolean addAll(Collection<? extends E> c)尾插 c 中的元素
E remove(int index)删除 index 位置元素
boolean remove(Object o)删除遇到的第一个 o
E get(int index)获取下标 index 位置元素
E set(int index, E element)将下标 index 位置元素设置为 element
void clear()清空
boolean contains(Object o)判断 o 是否在线性表中
int indexOf(Object o)返回第一个 o 所在下标
int lastIndexOf(Object o)返回最后一个 o 的下标
List< E > subList(int fromIndex, int toIndex)截取部分 list
import java.util.LinkedList;
import java.util.List;
public class Test {public static void main(String[] args) {LinkedList<Integer> list1 = new LinkedList<>();list1.add(1);   //add(elem)表示尾插list1.add(2);list1.add(3);list1.add(4);list1.add(5);System.out.println(list1.size());   //5System.out.println(list1);      //[1, 2, 3, 4, 5]//在起始位置插入0list1.add(0,0);    //add(index,elem);在index位置插入元素elemSystem.out.println(list1);      //[0, 1, 2, 3, 4, 5]list1.remove();     //remove();删除第一个元素,内部调用的是removeFirst()System.out.println(list1);  //[1, 2, 3, 4, 5]list1.removeFirst();    //removeFirst();删除第一个元素System.out.println(list1);  //[2, 3, 4, 5]list1.removeLast();     //removeLast();删除最后一个元素System.out.println(list1);  //[2, 3, 4]list1.remove(1);    //remove(index);删除index位置的元素System.out.println(list1);  //[2, 4]//contains(elem):检测elem元素是否存在,如果存在返回true,否则返回falseif(!list1.contains(1)){list1.add(0,1);}System.out.println(list1);  //[1, 2, 4]list1.addLast(1);System.out.println(list1);  //[1, 2, 4, 1]System.out.println(list1.indexOf(1));   //indexOf(elem);从前往后找第一个elem的位置 0System.out.println(list1.lastIndexOf(1));   //lastIndexOf(elem);从后往前找第一个elem的位置 3int elem = list1.get(0);    //get(index);获取指定位置元素System.out.println(elem);   // 1list1.set(0,100);   //set(index,elem);将index位置的元素设置为elemSystem.out.println(list1);  //[100, 2, 4, 1]//subList(from,to):用list1中[from,to)之间的元素构造一个新的LinkedList返回List<Integer> copy = list1.subList(0,3);System.out.println(list1);  //[100, 2, 4, 1]System.out.println(copy);   //[100, 2, 4]list1.clear();  //将list1中元素清空System.out.println(list1.size());   //0}
}
  1. LinkedList的遍历
public class Test {public static void main(String[] args) {LinkedList<Integer> list = new LinkedList<>();list.add(1);list.add(2);list.add(3);list.add(4);list.add(5);System.out.println(list);System.out.println("======for=====");for (int i = 0; i < list.size(); i++) {System.out.print(list.get(i) + " ");}System.out.println();System.out.println("======for each=====");for(int x : list){System.out.print(x + " ");}System.out.println();System.out.println("======Iterator=====");Iterator<Integer> it = list.iterator();while(it.hasNext()){System.out.print(it.next() + " ");}System.out.println();System.out.println("======ListIterator=====");ListIterator<Integer> lit = list.listIterator();while(lit.hasNext()){System.out.print(lit.next() + " ");}System.out.println();System.out.println("======ListIterator拓展=====");ListIterator<Integer> lit2 = list.listIterator(list.size());while(lit.hasPrevious()){System.out.print(lit.previous() + " ");}}//结果为://[1, 2, 3, 4, 5]//======for=====//1 2 3 4 5//======for each=====//1 2 3 4 5//======Iterator=====//1 2 3 4 5 //======ListIterator=====//1 2 3 4 5//======ListIterator拓展=====//5 4 3 2 1
}

ArrayList和LinkedList的区别

不同点ArrayListLinkedList
存储空间上物理上一定连续逻辑上连续,但物理上不一定连续
随机访问支持:O(1)不支持:O(N)
头插需要搬移元素,效率低O(N)只需修改引用的指向,时间复杂度为O(1)
插入空间不够时需要扩容没有容量的概念
应用场景元素高效存储+频繁访问任意位置插入和删除元素频繁

本篇文章到此,谢谢阅读,希望对您有帮助。

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

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

相关文章

【Redis】Set类型的常用命令与应用场景

目录 1.命令小结 2.命令解析 3.编码方式与应用场景 1.命令小结 &#xff08;1&#xff09;set的特点 1&#xff09;set中存放的数据也都是String类型 2&#xff09;set集合中的元素是无须的 3&#xff09;set集合中的元素是唯一的&#xff0c;不可重复 &#xff08;2&a…

MySql 之 Binglog 复制

复制是一种将数据从一个 MySQL 数据库服务器异步复制到另一个的技术。使用 MySQL 复制选项&#xff0c;您可以复制所有数据库、选定的数据库甚至选定的表&#xff0c;具体取决于您的使用情况。 前提条件 确保在源服务器上启用了二进制日志记录。确保复制配置中的所有服务器都有…

uniapp——h5的控制台调试、h5调试

介绍 小程序在调试的时候可以打开调试模式&#xff0c;可以看到console.log的打印情况。 但是H5运行到手机上没有默认的调试的模式&#xff0c;但是可以人为手动加一个。 如何实现 1、main.js文件 import Vconsole from ‘vconsole’ /** 关闭正式环境打印日志&#xff…

Centos7.5 安装和配置jdk17

目录 一、下载JDK17包 二、将安装包放入服务器 三、解压jdk包到/usr/lib/jvm 四、修改JDK环境配置 1、打开配置文件 2、最后一行插入 3、立即生效 4、检查版本 一、下载JDK17包 访问网址:Java Downloads | Oraclehttps://www.oracle.com/java/technologies/downloads…

音频功放工作原理:【B类】

上一节我们讲了A类音频功放的工作原理&#xff0c;也知道了它的优缺点&#xff1a; A类功放优点&#xff1a;高增益&#xff0c;低失真&#xff0c;音质好 A类功放缺点&#xff1a;热量高&#xff0c;效率低&#xff0c;功率小 为了解决A类功放的缺点&#xff0c;业界又引入…

重学SpringBoot3-集成Redis(十)之实时统计和分析

更多SpringBoot3内容请关注我的专栏&#xff1a;《SpringBoot3》 期待您的点赞&#x1f44d;收藏⭐评论✍ 重学SpringBoot3-集成Redis&#xff08;十&#xff09;之实时统计和分析 1. 实时统计和分析的常见场景2. 使用 Redis 数据结构进行实时统计3. 使用Redis String实现计数器…

原来机器学习那么简单——K近邻回归

引言&#xff1a; 在正文开始之前&#xff0c;首先给大家介绍一个不错的人工智能学习教程&#xff1a;https://www.captainbed.cn/bbs。其中包含了机器学习、深度学习、强化学习等系列教程&#xff0c;感兴趣的读者可以自行查阅。 一、什么是K近邻回归&#xff1f; K近邻回归&…

10.9QT对话框以及QT的事件机制处理

MouseMoveEvent(鼠标移动事件) widget.cpp #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);// 设置窗口为无边框&#xff0c;去掉标题栏等装饰this->setWi…

电脑缺失msvcr120.dll怎样修复,马上教你6种修复方法

在用电脑的时候&#xff0c;经常会碰到各种错误提示&#xff0c;比如“msvcr120.dll丢失”&#xff0c;导致的结果就是某些程序无法正常启动。那么&#xff0c;这个dll文件到底是啥&#xff0c;为什么会丢失&#xff0c;怎么解决呢&#xff1f;将通过这篇文章详细解释一下&…

智能优化算法-引力搜索优化算法(GSA)(附源码)

目录 1.内容介绍 2.部分代码 3.实验结果 4.内容获取 1.内容介绍 引力搜索优化算法 (Gravitational Search Algorithm, GSA) 是一种基于牛顿万有引力定律的元启发式优化算法&#xff0c;由Rashedi等人于2009年提出。GSA通过模拟天体之间的引力作用来搜索最优解&#xff0c;适用…

[ROS2]解决PyQt5和sip的各种报错问题 stderr: qt_gui_cpp

前言 编译ros环境的时候遇到了qt_gui_cpp各种编译问题&#xff0c;但是鉴于网上解决方法基本没有&#xff0c;故记录下来帮助后来者。整篇文章总结下来就是一句话&#xff1a;PyQt5和sip安装过程或安装版本有问题&#xff0c;需要重新安装。 问题与解决方法 如果PyQt5你是正…

P-Tuning v2:一种普遍有效的提示调整方法

人工智能咨询培训老师叶梓 转载标明出处 预训练语言模型通过微调&#xff08;fine-tuning&#xff09;来适应特定任务虽然效果显著&#xff0c;但存在训练成本高、参数存储量大等问题。为了解决这些问题&#xff0c;清华大学的研究者们提出了一种名为P-Tuning v2的提示调整&am…

colab+ngork本地访问多模态大模型

allenai/Molmo-7B-D-0924 1&#xff09;colab准备环境&#xff0c;我这里用的是l4 2&#xff09;安装对应的python库 !pip install transformers Pillow requests einops!pip install accelerate>0.26.0 bitsandbytes!pip install --no-deps accelerate bitsandbytes !p…

怎么将手机备忘录传送至电脑

在数字化时代&#xff0c;手机备忘录已成为我们生活中不可或缺的一部分。无论是记录购物清单、工作事项&#xff0c;还是灵感闪现的瞬间&#xff0c;手机备忘录都能随时记录下这些宝贵的信息&#xff0c;帮助我们防止遗忘。然而&#xff0c;有时候我们需要将这些备忘录内容转移…

数字影像技术平台推动可持续发展创意产业

在这个日新月异的数字时代&#xff0c;数字影像技术平台正以前所未有的力量&#xff0c;为可持续发展创意产业注入勃勃生机与无限可能。它们不仅是技术革新的前沿阵地&#xff0c;更是推动社会进步、促进文化繁荣的绿色引擎。 从高清细腻的VR体验&#xff0c;到震撼人心的AR互…

Tailwind Css的使用

1.Tailwind Css是什么 官网解释&#xff1a;Tailwind CSS 的工作原理是扫描所有 HTML 文件、JavaScript 组件以及任何 模板中的 CSS 类&#xff08;class&#xff09;名&#xff0c;然后生成相应的样式代码并写入 到一个静态 CSS 文件中。 我的理解是利用Tailwind CSS 提供的…

共享单车轨迹数据分析:以厦门市共享单车数据为例(十)

副标题&#xff1a;共享单车与地铁站出入口分布情况探究——以厦门市为例 假期结束了&#xff0c;我们满血复活&#xff0c;继续更新&#xff01; 本篇文章我们讨论共享单车与地铁出入口的关系&#xff0c;在上一篇文章中&#xff0c;我们讨论了综合得分指数最高的地铁站——…

利用可解释性技术增强制造质量预测模型

概述 论文地址&#xff1a;https://arxiv.org/abs/2403.18731 本研究提出了一种利用可解释性技术提高机器学习&#xff08;ML&#xff09;模型性能的方法。该方法已用于铣削质量预测&#xff0c;这一过程首先训练 ML 模型&#xff0c;然后使用可解释性技术识别不需要的特征并去…

安装echarts报错:request to https://registry.npmjs.org/echarts-gl failed

Hello&#xff01;欢迎各位新老朋友来看小弟博客&#xff0c;祝大家事业顺利&#xff0c;财源广进&#xff01;&#xff01; 主题&#xff1a;安装echarts报错&#xff1a;request to https://registry.npmjs.org/echarts-gl failed 第一&#xff1a;报错问题&#xff1a;链接…

Codeforces Round 923 (Div. 3) F. Microcycle

题目 【坑点】&#xff1a;不能先用拓扑排序去掉“线头”&#xff0c;然后找权重最小的边所在的环。因为去掉线头后&#xff0c;可能有的边不在环内。 e.g.有六条无向边 1 - 2 , 2 - 3, 1 - 3, 4 - 5, 5 - 6, 4 - 6, 1 - 4, 边1 - 4不在环内 wa代码&#xff1a; #include &…