数据结构与算法(Java语言版)课件 第5章 链表与LinkedList类_第1页
数据结构与算法(Java语言版)课件 第5章 链表与LinkedList类_第2页
数据结构与算法(Java语言版)课件 第5章 链表与LinkedList类_第3页
数据结构与算法(Java语言版)课件 第5章 链表与LinkedList类_第4页
数据结构与算法(Java语言版)课件 第5章 链表与LinkedList类_第5页
已阅读5页,还剩37页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第5章链表与LinkedList类2024/11/915.1链表的特点2024/11/92链表是由若干个节点组成,这些节点形成的逻辑结构是线性结构,节点的存储结构是链式存储,即节点的物理地址不必是依次相邻的。对于单链表,每个结点含有一个数据,并含有下一个节点的引用。对于双链表,每个节点含有一个数据,并含有上一个节点的引用和下一个结点的引用(Java实现的是双链表)2024/11/935.1链表的特点图示意的是有5个节点的双链表(省略了上一个节点的引用箭头示意)。注意,链表的节点序号是从0开始,每个节点的序号等于它前面的节点的个数。链表中的节点的物理地址不必是相邻的,因此,链表的优点是不需要占用一块连续的内存存储空间。图5.12024/11/945.1链表的特点

●删除头、尾节点的复杂度O(1)删除前面所示意5个节点的的链表的头节点(大象-节点)后的示意图。2024/11/955.1链表的特点

●查询头、尾节点的复杂度O(1)查询狮子和鳄鱼的时间复杂度都是O(1)。2024/11/965.1链表的特点

●添加头尾节点的复杂度O(1)要给图5.1所示意的链表的添加新的尾节点(企鹅-节点),根据双链表保存的尾节点的地址,找到尾节点(鳄鱼-节点),将这个尾节点中的下一个节点的引用设置成新添加的节点(企鹅-节点)的引用,将添加的新节点(企鹅-节点)中的上一个节点的引用设置成鳄鱼-节点的引用,将添加的新节点(企鹅-节点)中的下一个节点的引用设置成null,即让新添加的节点成为尾结点。2024/11/975.1链表的特点●查询中间节点的时间复杂度O(n)链表的节点的物理地址不是相邻的,节点通过互相保存引用链接在一起。

2024/11/985.1链表的特点●删除中间节点的复杂度O(n)链表的节点的物理地址不是相邻的,节点通过互相保存引用链接在一起。

删除了老虎-节点2024/11/995.1链表的特点●插入中间节点的复杂度O(n)

插入新节点后,新链表中的节点序号按新的链表长度从0开始排列。2024/11/9105.1链表的特点●插入中间节点的复杂度O(n)图5.1的链表中插入新的第2个节点(羚羊-节点)5.2创建链表2024/11/911链表由Java集合框架(JavaCollectionsFramework,JCF)中的LinkedList<E>泛型类所实现。2024/11/9125.2创建链表LinkedList<E>泛型类实现了Java集合框架中的List和Queue泛型接口。LinkedLis<E>t泛型类继承了List和Queue泛型接口中的default关键字修饰的方法(去掉了该关键字),实现了List和Queue泛型接口中的抽象方法。2024/11/9135.2创建链表例子1Example5_1.java使用LinkedList<E>泛型类声明链表时,必须要指定E的具体类型,类型是类或接口类型(不可以是基本类型,比如int、float、char等),即指定链表中节点里的对象的类型。例如,指定E是String类型:LinkedList<String>listOne=newLinkedList<>();或LinkedList<String>listOne=newLinkedList<String>();例子1中的主类Example5_1中首先创建一个空链表listOne,然后向空链表listOne添加4个节点,随后再用listOne创建链表listTwo。修改listTwo节点的数据,并不影响listOne节点中的数据。5.3查询与相等2024/11/914查询链表节点中的数据的常用方法:

booleanequals(Objectlist)如果此链表和list长度相同,并且对应的每个节点中的对象也相等,那么方法返回true,否则返回flase。2024/11/9155.3查询与相等例子2People.javaExample5_2.java例子2中的主类Example5_2中比较了get(intindex)方法和getLast()方法的运行时间。例子2中的People类重写了booleanequals(Objecto)方法.2024/11/9165.3查询与相等例子3RandomLayMines.javaExample5_3.java

主类Example5_3使用layMines(char[][]area,intamount)方法布雷39颗。2024/11/9175.3查询与相等例子4TeamGame.javaExample5_4.java

5.4添加2024/11/918链表添加节点常用方法:

2024/11/9195.4添加例子5Example5_5.java例子5中的主类Example5_5中比较了voidaddLast(Ee)方法和voidadd(intindex,Ee)方法的运行时间。5.5删除2024/11/920链表删除节点常用方法:

2024/11/9215.5删除例子6RandomNumber.java例子6中RandomNumber类的getRandom(intnumber,intamount)方法通过随机删除链表中的节点来得到若干个随机数。Example5_6.java例子6中的主类Exmple5_6使用RandomNumber类的getRandom(intnumber,intamount)方法模拟双色球,同时过滤一个链表。2024/11/9225.5删除例子7HandleRecurring.javaExample5_7.java有时候需要处理数组中重复的数据,即让重复的数据只保留一个。在某些场景下,数据重复属于冗余问题。冗余可能给具体的实际问题带来危害,比如,你在撰写一篇文章时,用编辑器同时打开了一个文档多次,那么有时候就会引起混乱。所以,应当只打开文档一次,以免在修改,保存文档时发生数据处理不一致的情况。例子7中,HandleRecurring类的handleRecurring(LinkedList<E>list)方法处理链表list中重复的数据,该方法返回的链表中没有重复的数据(对于重复的数据,保留其中一个)。5.6更新2024/11/923链表更新节点的常用方法:

Collections类的静态方法static<T>voidfill(List<?superT>list,Tobj)将链表list的每个节点中的对象都设置为参数obj指定的对象。2024/11/9245.6更新例子8Example5_8.java例子8的主类Example5_8使用set(intindex,Eelement)方法和fill(List<?superT>list,Tobj)方法更新链表节点中的对象。5.7链表的视图2024/11/925链表的视图是由链表中若干个节点所构成,其状态变化和链表是同步的。视图的好处是,可以将经常需要修改的节点放在一个视图中,有利于数据的一致性处理。

使用视图时,要注意视图中节点和原链表节点的对应关系。2024/11/9265.7链表的视图List<E>subList(intfromIndex,inttoIndex)方法是AbstractList类所实现的List接口中的一个方法(AbstractList类是LinkedList的间接父类)。该方法返回一个当前链表中节点序号fromIndex(含)和toIndex(不含)之间的节点构成的视图。需要特别注意的是,一旦链表添加或删除节点,就会破坏视图的索引,即会影响之前链表subList()方法返回的视图,这个视图将无法再继续被使用(如果继续使用,运行时刻会触发ConcurrentModificationException异常),链表必须用subList()方法重新返回一个新的视图。更改视图的节点(增加或删除节点)或对节点的数据的修改都会使得当前链表发生同步的改变。2024/11/9275.7链表的视图使用视图时,要注意视图中节点和原链表节点的对应关系。原链表list中狮子节点是第1个节点,但在视图listView中狮子节点是第0个节点,原链表list中老虎节点是第2个节点,但在视图listView中老虎节点是第1个节点,原链表list中猎豹节点是第3个节点,但在视图listView中猎豹节点是第2个节点。2024/11/9285.7链表的视图使用视图时,要注意视图中节点和原链表节点的对应关系。如果视图listView增加一个节点,比如尾节点:鬣狗那么原链表list会同步更新、发生变化,猎豹节点和河马节点之间多了一个鬣狗节点:2024/11/9295.7链表的视图例子9Example5_9.java例子9的主类Example5_9使用链表的视图更新链表节点中的天气信息。5.8链表的排序2024/11/930publicdefaultvoidsort(Comparator<?superE>c)方法是List接口的默认排序方法(default关键字修饰的方法),LinkedList继承了该排序方法(去掉了关键字default)。该排序方法的参数c是Comparator泛型接口,Comparator泛型接口是一个函数接口,即此接口中的抽象方法只有一个:intcompare(Ta,Tb),此方法比较两个参数a和b的顺序,返回值是正数表示a大于b,返回负数表示a小于b,返回零表示a等于b。2024/11/9315.8链表的排序Comparator是一个函数接口,因此在使用该方法时,可以向参数c传递一个Lambda表达式,该Lambda表达式必须是2个参数,Lambda表达式中必须有return语句,返回的值是int型数据(和其代表的intcompare(Ta,Tb)方法保持一致)。例如sort((a,b)->{if(a.height>b.height)return1;elseif(a.height<b.height)return-1;elsereturn0;})

2024/11/9325.8链表的排序例子10Student.java例子10的主类Example5_10分别按学生的数学和英文成绩升序排序链表、降序排序链表。Example5_10.java5.9遍历链表2024/11/933某些集合根据其数据存储结构和所具有的操作也会提供返回数据的方法,例如LinkedList类中的get(intindex)方法将返回当前链表中第index节点中的对象。LinkedList的存储结构不是顺序结构,即节点的物理地址不必是依次相邻的,因此,链表调用get(intindex)方法的速度比顺序存储结构的集合调用get(intindex)方法的速度慢。当用户需要遍历集合中的节点时,应当使用该集合提供的迭代器,而不是让集合本身来遍历其中的节点。2024/11/9345.9遍历链表单向迭代器是从链表的头节点开始,遍历到尾节点。●单向迭代器链表对象可以使用Iterator<E>iterator()方法获取一个实现Iterator接口的对象,该对象就是针对当前链表的单向迭代器。迭代器内部使用了游标技术,单向迭代器的游标的初始状态是指向链表的头节点的前面,如果游标可以向后移动(向链表的尾节点方向),单向迭代器调用hasNext()方法返回true,否则返回false。连续的调用next()方法会将游标移动到尾节点,这时游标将无法向后移动,再调用next()方法否则触发运行异常NoSuchElementException(链表是空链表,直接调用next()方法也会触发运行异常NoSuchElementException)。2024/11/9355.9遍历链表●双向迭代器链表对象可以使用ListIterator<E>listIterator()方法获取一个实现ListIterator接口的对象(ListIterator接口是Iterator的子接口),该对象就是针对当前链表的双向迭代器。双单向迭代器是双游标迭代器,一个向后游标(向链表的尾节点方向),一个向前游标(向链表的头节点方向)。双游标是同时移动,向前游标在向后游标的后面。

初始状态向后游标指向头节点的前面,向前游标指向头节点。2024/11/9365.9遍历链表●遍历与更新迭代器对链表实施的添加、删除、更新节点等操作一直等到迭代器遍历链表完毕再生效。双向迭代器调用next()或previous()方法返回节点中的数据后,迭代器紧接着调用add(Eobj)方法,可以在该节点后插入一个节点(新节点序号从当前节点开始递增),调用set(Eobj)方法可以更新该节点中的数据,调用remove()方法可以删除该节点。单向迭代器在遍历链表时也可以同时更新链表,但只能删除节点。单向迭代器调用next()方法返回节点中的数据后,迭代器紧接着调用remove()方法可以删除该节点。2024/11/9375.9遍历链表●遍历与锁定单向或双向迭代器在遍历链表时,将不允许链表本身调用方法更改链表节点的结构。单向或双向迭代器在遍历链表时,将不允许链表本身调用方法更改链表节点的结构,即不允许链表调用方法增加节点、删除节点、排序链表,但允许链表调用set(intindex,Eobj)方法更新节点中的数据,因为更新节点只是更新链表的节点中的数据,不属于更改链表的节点的结构。

在迭代器没有结束遍历之前,如果链表进行增加节点、删除节点、排序链表这些操作,程序运行时(无编译错误)将触发java.util.ConcurrentModificationException异常。程序必须等到迭代器被使用完毕,才允许链表调用add()、remove()方法添加、删除节点或排序链表。2024/11/9385.9遍历链表●for-each语句链表获得迭代器后,在使用迭代器之前又对链表进行了更新,比如添加、删除或排序链表,那么就无法再使用该迭代器遍历链表。如果想使用迭代器,就必须让链表重新返回一个新的迭代器。使用for-each语句遍历一个链表时,禁止当前链表调用add()、remove()方法添加、删除节点或排序链表,其原因是,for-each算法的内部中启用了迭代器。2024/11/9395.9遍历链表例子11例子11的主类Example5_11分别使用单向迭代器和双向迭代器遍历了链表,在遍历的过程中也更新了链表。Example5_11.java2024/11/9405.9遍历

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论