在这一篇里,要讲的是如何使用迭代器对链表进行相关的操作,比如删除,获取,插入等操作,那首先介绍一下什么是迭代器,java里面的迭代器的实用性很大,在我们实际对链表进行删除操作时,如果是要对某个限制条件下的所有链表数据都删除,如果是用普通的指针,那就必须每次都对链表进行遍历查找,符合了条件进行删除,而效率很低,而不像数组,有固定的下标位,所以我们设法给予一个类似数组下标的东西来表明链表的位置。
这时我们使用了一种类,叫迭代器类,迭代器类包含对数据结构的数据项的引用,并用来遍历这些结构的对象。
好了,大概介绍了一下,我们来看看迭代器的具体使用吧:
这里笔者用迭代器去代替一些链表操作,也就是这些操作可以在链表里执行的,但是放在迭代器里能更加明白其用法,首先创建一个链表:
<span style="font-size:18px;">public class Link {
private long dData;
private Link next;
public Link(long dd){
dData = dd;
}
public void displayLink(){
System.out.print(dData + " ");
}
}</span>
这里有long型的数据,也有next的引用,作为标识下个链节点的引用,然后我们来创建链表:
<span style="font-size:18px;">public class LinkList {
private Link first;
public LinkList(){
first = null; //构造函数初始化首节点
}
public Link getFirst() { //获取第一个节点
return first;
}
public void setFirst(Link first) { //设置第一个节点
this.first = first;
}
public boolean isEmpty(){ //判断链表是否为空
return (first == null);
}
public LinkIterator myIterator(){ //定义迭代器,与之联系起来
return new LinkIterator(this);
}
public void displayLinklist(){ //打印出链表中的元素
Link current = first;
while (current != null) {
System.out.print(current.dData + " ");
current = current.next;
}
System.out.println("");
}
}</span>
其他函数没什么好说的,主要要注意一下关于链表和迭代器之间的联系,在链表中创建迭代器时,传递给迭代器一个引用,这个引用储存在迭代器的一个字段中,这样迭代器就可以访问链表中的私有数据字段了。
然后是迭代器类的实现:
public class LinkIterator {
private Link current;
private Link previous;
private LinkList outlist;
public LinkIterator(LinkList mLinkList){ //构造函数,同时进行将迭代器置于表头
outlist = mLinkList;
reset();
}
public void reset(){ //将迭代器置于表头方法
current = outlist.getFirst();
previous = null;
}
public boolean atEnd(){ //判断迭代器是否位置在表尾
return (current.next == null);
}
public void nextLink(){ //将迭代器的位置向后移动一位
previous = current;
current = current.next;
}
public Link getCurrent(){ //返回此时迭代器所指链节点的值
return current;
}
public void inserAfter(long dd){ //插入迭代器所指链节点的后面
Link newLink = new Link(dd);
if (outlist.isEmpty()) {
outlist.setFirst(newLink);
current = newLink;
}
else {
newLink.next = current.next;
current.next = newLink;
nextLink();
}
}
public void insertBefore(long dd){ //插入迭代器所指链节点对的前面
Link newlink = new Link(dd);
if (previous == null) {
newlink.next = outlist.getFirst();
outlist.setFirst(newlink);
reset();
}else {
newlink.next = previous.next;
previous.next = newlink;
current = newlink;
}
}
public long deleteLink(){ //删除迭代器所指的链节点
long data = current.dData;
if (previous == null) {
outlist.setFirst(current.next);
reset();
}else {
previous.next = current.next;
if (atEnd()) {
reset();
}else {
current = current.next;
}
}
return data;
}
}
这个迭代器类实现要注意节点直接的关系,注意判断节点的位置和表是否为空,这两点经常会忘记。然后就是主要函数的调用了,这里笔者分为几个操作进行功能的调用:
public class IteratorTest {
public static void main(String[] args) throws IOException {
LinkList mLinkList = new LinkList();
LinkIterator mIterator = mLinkList.myIterator();
long value;
mIterator.inserAfter(20);
mIterator.inserAfter(40);
mIterator.inserAfter(80);
mIterator.insertBefore(60);
while (true) {
System.out.println("please input the letter to operate the Iterator: ");
System.out.println("you can input the word of s,r,g,n,b,a,d: ");
System.out.flush();
int m = getChar();
switch (m) {
case 's':
if (!mLinkList.isEmpty()) {
mLinkList.displayLinklist();
}else {
System.out.println("the linklist is empty");
}
break;
case 'r':
mIterator.reset();
break;
case 'g':
if (!mLinkList.isEmpty()) {
value = mIterator.getCurrent().dData;
System.out.println("Return data is : " + value);
}else {
System.out.println("the linklist is empty");
}
break;
case 'n':
if (!mLinkList.isEmpty() && !mIterator.atEnd()) {
mIterator.nextLink();
}else {
System.out.println("something happening");
}
break;
case 'b':
if (!mLinkList.isEmpty()) {
System.out.print("input the word you want to insert ");
System.out.flush();
value = getInt();
mIterator.insertBefore(value);
}else {
System.out.println("something happening");
}
break;
case 'a':
if (!mLinkList.isEmpty()) {
System.out.print("input the word you want to insert ");
System.out.flush();
value = getInt();
mIterator.inserAfter(value);
}else {
System.out.println("something happening");
}
break;
case 'd':
if (!mLinkList.isEmpty()) {
value = mIterator.deleteLink();
System.out.print("the deleted data is : " + value);
}else {
System.out.println("something happening");
}
break;
default:
System.out.println("Invalid entry");
break;
}
}//end while
}//end main
public static String getString() throws IOException{
InputStreamReader inReader = new InputStreamReader(System.in);
BufferedReader buf = new BufferedReader(inReader);
String mString = buf.readLine();
return mString;
}
public static char getChar() throws IOException{
char a;
a = getString().charAt(0);
return a;
}
public static int getInt() throws IOException{
int a ;
String s = getString();
a = Integer.parseInt(s);
return a;
}
}
主函数的调用要注意对表是否为空的判断,以及对迭代器位置的判断,如果为空或者在尾部,应该做出相应的处理,这里更好应该在方法中就进行自动的判断,笔者在这里实现的是单链表,大家可以去尝试实现以下双向链表是如何实现的。
下面是运行结果:
好了,迭代器就讲到这里,大家有疑问可以评论。