Java数据结构和算法-链表(5-迭代器)
来源:互联网 发布:张伯伦生涯场均数据 编辑:程序博客网 时间:2024/05/17 04:36
在链表中可以通过find()方法来查找到某一个特定的值,也可以通过delete方法删除某一个特定的值。这些操作都有一个搜索的工作,以找到特定的链接点。
在链表中进行一次某个值的查找删除或插入是简单的。但是现实中,经常会进行的是对某些特定的链接点的操作,而这些操作也都要进行搜索的工作。例如:要查找出所有某班成绩低于平均成绩的同学,要改变公司所有拥有最低工资的员工工资。这些都要进行搜索。
但是链表不是数组,链表没有下标,如果是数组的话,可以通过跟踪下标来确定当前搜索到的位置,当查找到第一个符合条件的值的同时,返回当前的下标,从而使得在继续查找下一个符合条件的值时,可以从该下标开始。链表不可以,链表在返回了符合条件的值后,必须从头开始查找下一个符合条件的值。如果有一个保存当前链接点的引用,在下一次查找时,从该引用的链接点进行步进,这样效率就会提高很多。
可能有人在说到“保存当前链接点的引用”时,就想到了在之前链表的介绍中,在链表类中定义的current,用current来存取一个链接点,然后使current递增,来移动到下一个链接点。
这种方法存在的一个问题是,只能进行一种引用。但是在现实中可能不止一个,就像经常要使用多个下标。并且需要引用的数目是未知的,所以这个引用不应该定义在链表内,而应该封装在一个独立的类中,并且这个类不能和链表相同。
迭代器
迭代器类是封装了对数据结构的数据项的引用的类,并用来遍历这些对象。在介绍的初始定义如下:
class ListIterator() { private Link current; //...}
它包含了一个对链接点的引用。
在产生链表后,可以通过调用某些方法来创建迭代器,比如下面的操作:
public static void main(String[] args) { LinkList linkList = new LinkList(); ListIterator iter1 = linkList.getIterator(); Link link = iter1.getCurrent(); iter1.nextLink();}
在上面的代码中通过getIterator()来获取链表的迭代器,创建这个迭代器之后,可以通过它的递增,来指向下一个链接点。当然迭代器可以不止一个,迭代器总是指向链表中的一些链接点,它通过引用与链表相关联,但不等同于它就是链表或者链接点,如下图:
迭代器的其他特性
在链表章节的其他程序中,都会定义一个previous的字段,这使得链表进行删除或者插入操作时更加便捷,因此在迭代器中也封装了这个字段。
另外,在链表操作中我们可能会在表头进行一下操作,所以访问first也是必要的,但是first是链表的私有字段,迭代器要如何访问这个字段呢?
一种方式是在链表创建迭代器时,向迭代器传递一个对first的引用给迭代器,然后将这个引用存贮在迭代器的某个字段中。
还有一种方式是在链表中设一个公有方法getFirst来获取first的引用。不过这种方式有一个弊端是允许任何人修改first,这是危险的。
迭代器的方法
我们将链表中的部分方法也通过迭代器来实现,这样可以使得迭代器更加灵活和强大,例如迭代器包含以下的方法:
- reset()–把迭代器设在表头
- nextLink()–将迭代器移动到下一个链接点
- getCurrent()–获取当前迭代器指向的链接点
- insertAfter()–在迭代器指向的链接点之后插入
- insertBefore()–在迭代器指向的链接点之前插入
- atEnd()–判断迭代器是否在表尾
- deleteCurrent()–删除当前迭代器指向的链接点
哪些任务由链表完成,哪些由迭代器完成,这并不好决定。insertFirst的插入位置是固定的不需要搜索所以将这个方法由链表来实现,而insertBefore这需要搜索工作,所以就有迭代器来实现。displayList可以通过链表也可以通过迭代器来实现,不过在下面的介绍中,我们通过链表实现。
迭代器的Java代码
class Link { private int iData; private Link next; public Link(int d) { iData = d; } public int getIData() { return iData; } public void setIData(int d) { iData = d; } public void displayLink() { System.out.println("Link: " + iData); } //next的get和set方法}//end Linkclass LinkList { private Link first; public ListIterator getIterator() { return new ListIterator(this); } public Link getFirst() { return first; } public void setFirst(Link l) { first = l; } public void insertFirst(int d) { Link newLink = new Link(d); newLink.next = first; first = newLink; } public boolean isEmpty() { return (first == null); } public void displayList() { Link current = first; while(current != null) { current.displayLink(); } }}//end LinkListclass ListIterator { private Link previous; private Link current; private LinkList myList; public ListIterator(LinkList ll) { myList = ll; reset(); } public void reset() { current = myList.getFirst(); previous = null; } public boolean atEnd() { return (current.getNext() == null); } public void nextLink() { if(atEnd()) { reset(); } else { previous = current; current = current.getNext(); } } public void insertAfter(int d) { Link newLink = new Link(d); if(isEmpty()) { myList.setFirst(newLink); current = newLink; } else { newLink.setNext(current.getNext()); current.setNext(newLink); nextLink(); } } public void insertBefore(int d) { Link newLink = new Link(d); if(previous == null) { myList.setFirst(newLink); reset(); } else { newLink.setNext(current); previous.setNext(newLink); current = newLink; } } public int deleteCurrent() { Link temp = current; if(previous == null) { myList.setFirst(current.next); reset(); } else { previous.setNext(current.getNext()); if(atEnd()) reset(); else current = current.getNext(); } return temp.getIData(); } public int getCurrent() { return current.getIData(); }}//end ListIterator class IteratorApp { public static void main(String[] args) { LinkList linkList = new LinkList(); ListIterator ite = linkList.getIterator(); ite.insertAfter(21); ite.insertAfter(14); ite.insertAfert(45); ite.insertAfter(30); ite.insertAfter(67); ite.reset(); if(ite.getCurrent()%3 == 0) ite.deleteCurrent(); while(!ite.atEnd()) { ite.nextLink(); if(ite.getCurrent()%3 == 0) ite.deleteCurrent(); } linkList. }}
在上面的代码中,deleteCurrent方法当删除了当前所指向的链接点之后,current可能指向下一个,上一个或者回到表头,因为在删除链接点之后,迭代器仍指向附近的节点,能够便于下一个操作,而且如果指向上一个链接点,由于不是双向链表,链接点没有关于previous的引用,所以指向上一个链接点会比较复杂,因此deleteCurrent最后current会指向下一个链接点。
- Java数据结构和算法-链表(5-迭代器)
- Java数据结构和算法(链表)
- Java数据结构和算法--链表
- Java数据结构和算法--链表
- Java数据结构和算法--链表
- Java 数据结构和算法 链表
- JAVA数据结构和算法
- Java 数据结构和算法
- java 数据结构和算法
- Java数据结构和算法
- java数据结构和算法
- Java数据结构和算法
- java数据结构和算法
- java数据结构和算法
- java数据结构和算法
- java数据结构和算法
- java数据结构和算法
- java数据结构和算法
- 高精度加法
- 参数服务器代码解读(1)
- Spring事务理解-1
- 截屏工具类
- 统一设置根路径
- Java数据结构和算法-链表(5-迭代器)
- js依赖注入的设计思想
- java jar 打包命令
- 哈夫曼编码器
- Java的位运算符详解实例——与(&)、非(~)、或(|)、异或(^)
- 【Day63】PHP支付宝服务窗API接口的开发
- java开发系统内核:进程切换
- 2016 微软技术大会所有视频下载链接,包含人工智能、物联网、云、大数据和BI等所有最新技术和方案视频
- 《从零开始学Swift》学习笔记(Day 57)——Swift编码规范之注释规范:文件注释、文档注释、代码注释、使用地标注释