当前位置: 首页 > news >正文

无头单向非循环java版的模拟实现

【本节目标】

1.ArrayList的缺陷

2.链表

1. ArrayList的缺陷

上节课已经熟悉了 ArrayList 的使用,并且进行了简单模拟实现。通过源码知道, ArrayList 底层使用数组来存储元素:
public class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{// ...
// 默认容量是10private static final int DEFAULT_CAPACITY = 10;//...
// 数组:用来存储元素transient Object[] elementData; // non-private to simplify nested class access// 有效元素个数private int size;public ArrayList(int initialCapacity) {if (initialCapacity > 0) {this.elementData = new Object[initialCapacity];} else if (initialCapacity == 0) {this.elementData = EMPTY_ELEMENTDATA;} else {throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);}}
// ...
}
由于其底层是一段连续空间,当 ArrayList 任意位置插入或者删除元素时,就需要将后序元素整体往前或者往后 搬移,时间复杂度为 O(n) ,效率比较低,因此 ArrayList 不适合做任意位置插入和删除比较多的场景 。因此: java集合中又引入了LinkedList ,即链表结构。

2. 链表

2.1 链表的概念及结构

链表是一种 物理存储结构上非连续 存储结构,数据元素的 逻辑顺序 是通过链表中的 引用链接 次序实现的 。
实际中链表的结构非常多样,以下情况组合起来就有 8 种链表结构:
1. 单向或者双向
2. 带头或者不带头
3. 循环或者非循环
虽然有这么多的链表的结构,但是我们重点掌握两种 :
头单向非循环链表结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。另外这种结构在笔试面试中出现很多。
无头双向链表:在Java的集合框架库中LinkedList底层实现就是无头双向循环链表。

2.2 无头单向非循环链表的实现

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

要有链表首先得有节点
如下就是使用内部类创建了个头结点
有数值和next节点的地址
在创建一个成员变量head,指向头结点。未初始化默认为null
我们可以写链表的插入
链表的头插不需要考虑是否为空的情况
链表的尾差需要考虑为空的情况,如果是空就直接返回,不进行插入
while(cur.next!=null)
这个循环是遍历到最后一个链表,再将它的next改为新节点的地址即可
随机位置插入
1.考虑给的位置是否合法
2.给的是0或者给的链表长度
3.在范围内的值找到index前一个的链表
4.进行连接
1.合法性
写了一个异常类
写了一个函数捕捉这个异常
再用try-catch来处理异常
2.给的是0或者给的链表长度
如果给的是0就进行头插
如果给的是链表长度就进行尾差
剩下的就比较简单
用了一个函数进行寻找index的前一个位置
再进行连接
链表的打印
再测试下插入是否满足要求
可见插入是满足需求的
是否包含某个元素

删除第一个数值为val的节点
测试
删除所有为为val的节点
测试
确实没有1出现,可见全部删除
删除所有存在val值的节点还有一个方法,创建一个哨兵位
测试
也是可以的

2.3总代码

接口

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

indexNotLegalException.java

public class indexNotLegalException extends   RuntimeException{public indexNotLegalException(){}public indexNotLegalException(String msg){super(msg);}
}

LinkList.java

public class LinkList implements Ilinklist {static class ListNode{public int val;ListNode next;public ListNode(int val) {this.val = val;}}ListNode head;@Overridepublic void addFirst(int val) {//链表的头插ListNode node=new ListNode(val);node.next=head;head=node;}public void addLast(int val){//链表的尾差ListNode node=new ListNode(val);if(head==null){head=node;return;}ListNode cur=head;while(cur.next!=null){cur=cur.next;}cur.next=node;}public int getSize(){//获取链表的长度ListNode cur=head;int count=0;while(cur!=null){count++;cur=cur.next;}return count;}public  void addIndex(int index,int val){//1.判断合法性try{cheakIndexofAddIndex(index);}catch(indexNotLegalException e){e.printStackTrace();return;}//2.index==0||index==size()if(index==0){addFirst(val);return;}if(index==getSize()){addLast(val);return;}//3.找到index的前一个位置ListNode cur=findIndexSubOne(index);//4.进行连接ListNode node=new ListNode(val);node.next=cur.next;cur.next=node;}@Overridepublic boolean contains(int val) {ListNode cur=head;while(cur!=null){if(cur.val==val){return true;}cur=cur.next;}return false;}@Overridepublic void remove(int val) {   //删除第一个节点为val的值if(head==null){return;}ListNode cur=head;if(cur.val==val){head=head.next;return;}while(cur.next!=null){if(cur.next.val==val){cur.next=cur.next.next;return;}cur=cur.next;}}@Overridepublic void removeAllKey(int val) {//删除链表所有值为val的节点/*      if(head==null){return;}ListNode prev=head;ListNode cur=head.next;while(cur!=null){if(cur.val==val){prev.next=cur.next;cur=cur.next;}else{prev=cur;cur=cur.next;}}if(head.val==val){head=head.next;}*/ListNode Head=new ListNode(0);Head.next=head;ListNode temp=Head;while(temp.next!=null){if(temp.next.val==val){temp.next=temp.next.next;}else{temp=temp.next;}}head=Head.next;}@Overridepublic void clear() {}@Overridepublic void display() {ListNode cur=head;while(cur!=null){System.out.print(cur.val+" ");cur=cur.next;}System.out.println();}private void cheakIndexofAddIndex(int index) throws indexNotLegalException{//判断指定位置插入的index是否合法if(index<0||index>getSize()){throw new indexNotLegalException("AddIndex的index不合法");}}private ListNode findIndexSubOne(int index){ListNode cur=head;while(index-1>0){cur=cur.next;index--;}return cur;}}

test.java

public class test {public static void main(String[] args) {LinkList linkList=new LinkList();linkList.addFirst(1);linkList.addFirst(1);linkList.addFirst(1);linkList.addFirst(1);//上面是链表的头插linkList.display();System.out.println("==============");linkList.removeAllKey(1);//删除所有拥有1的节点linkList.display();}
}

http://www.lryc.cn/news/450939.html

相关文章:

  • Bert Score-文本相似性评估
  • Pyenv管理Python版本,conda之外的另一套python版本管理解决方案
  • 快速实现AI搜索!Fivetran 支持 Milvus 作为数据迁移目标
  • css的页面布局属性
  • RTE 大会报名丨AI 时代新基建:云边端架构和 AI Infra ,RTE2024 技术专场第二弹!
  • 【React】入门Day01 —— 从基础概念到实战应用
  • <<机器学习实战>>10-11节笔记:生成器与线性回归手动实现
  • 链表OJ经典题目及思路总结(一)
  • 初识chatgpt
  • 【60天备战2024年11月软考高级系统架构设计师——第33天:云计算与大数据架构——大数据处理框架的应用场景】
  • 如何设计具体项目的数据库管理
  • 对于 Vue CLI 项目如何引入Echarts以及动态获取数据
  • 【Linux笔记】在VMware中,为基于NAT模式运行的CentOS虚拟机设置固定的网络IP地址
  • 一文上手Kafka【中】
  • Ubuntu如何如何安装tcpdump
  • 3-3 AUTOSAR RTE 对SR Port的作用
  • hive/impala/mysql几种数据库的sql常用写法和函数说明
  • 论文阅读:LM-Cocktail: Resilient Tuning of Language Models via Model Merging
  • 8640 希尔(shell)排序
  • Linux 安装redis主从模式+哨兵模式3台节点
  • [BCSP-X2024.小高3] 学习计划
  • Android Debug Bridge(ADB)完全指南
  • 再次重逢,愿遍地繁花
  • 数据结构和算法基础(一)
  • 【超长好文】网络安全从业者面试指南
  • 基于大数据的高校新生数据可视化分析系统
  • 【cache】浅析四种常用的缓存淘汰算法 FIFO/LRU/LFU/W-TinyLFU
  • STM32的DMA技术介绍
  • C++11 多线程编程-小白零基础到手撕线程池
  • 智源研究院与百度达成战略合作 共建AI产研协同生态