用迭代器优化链表

在单链表那篇文章中,我们实现了find()方法,根据指定的值找到结点。这个方法是从表头开始考察每个链结点,直到链接点的值和给定的值匹配

public Link find(int key){
        Link current=first;//指向第一个结点
        while (current.data1!=key){
            if(current.next==null){
                return null;//到达链表尾部返回null
            }else{
                current=current.next;//没找到移到下一个结点
            }
        }
        return current;
    }

其他的操作例如删除指定值得结点或者向前和向后插入新节点,都包含有链表上的搜索工作,以找到指定结点。但是这些方法都没有提供用户任何遍历上的控制手段。

在数组中,可以用下标跟踪所在位置。然后在链表中,没有固定的下标。使用find()方法虽然可以找到合适的链结点,但是这个方法要进行多次比较,效率就会很低。如果能从链结点到链接点步进,检查每个链接点是否符合某个标准,在执行操作,效率就会高很多。

这时我们就可以用到迭代器。那什么是迭代器呢?

迭代器就是一个引用,它被封装在一个类对象里面,并指向相关联的链表中的链结点。它里面封装了能对链接点进行某些操作的方法。

定义迭代器类

class ListIterator{
    private Link current;//指向当前结点
    private Link previous;//指向前一个
    private LinkList ourList;//指向链表
        //构造函数初始化
    public ListIterator(LinkList list){
        ourList=list;
        reset();
    }
        //初始化变量
        public void reset(){
        current=ourList.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 insertAfter(long dd){
        Link newLink=new Link(dd);//新增的结点
        //判断链表是否为空,为空则在表头插入
        if(ourList.isEmpty()){
            ourList.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=ourList.getFirst();
            ourList.setFirst(newLink);
            reset();
        }else{
            newLink.next=current;
            previous.next=newLink;
            current=newLink;
        }
    }
    //删除当前结点
    public void deleteCurrent(){
        long value=current.aData;
        //如果是表头
        if(previous==null){
            ourList.setFirst(current.next);
            reset();
        }else{
            previous.next=current.next;
            if(atEnd()){
                reset();//迭代器达到结尾,返回开头
            }else{
                current=current.next;
            }
        }
    }

链接点类

//结点
public class Link {
    public long aData;
    public Link next;
    //构造函数初始化
    public Link(long dd){
        this.aData=dd;
    }
    public void displayLink(){
        System.out.println(aData+",");
    }
}

链表类

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 void displayList(){
        Link current=first;
        while(current!=null){
            current.displayLink();
            current=current.next;
        }
    }
    //初始化迭代器
    public ListIterator getIterator(){
        return new ListIterator(this);
    }
}

测试代码

public class Test {
    public static void main(String[] args) {
        LinkList list=new LinkList();
        ListIterator it=list.getIterator();
        it.insertAfter(1);
        it.insertAfter(2);
        it.insertAfter(3);
        it.insertAfter(4);
        it.insertBefore(5);
        list.displayList();
        System.out.println("-----------------");
        it.reset();//迭代器重置
        //删除能整除3的数据
        Link aLink =it.getCurrent();
        if(aLink.aData%3==0){
            it.deleteCurrent();
            
        }
        while(!it.atEnd()){
            it.nextLink();
            aLink=it.getCurrent();
            if(aLink.aData%3==0){
                it.deleteCurrent();
                
            }
        }
        list.displayList();
    }
}

结果

1,
2,
3,
5,
4,
-----------------
1,
2,
5,
4,

 

posted @ 2017-03-22 22:51  一只会编程的猫  阅读(896)  评论(0编辑  收藏  举报