来源:互联网 发布:java spring 拦截器 编辑:程序博客网 时间:2024/06/11 18:21

第二次博客,希望能有第三次。这次主要聊聊表、列表、List(同一种事物)。

抽象数据类型 ADT

抽象数据类型(abstract data type,ADT),是带有一组操作的一些对象的集合。说人话:好几个相同类型的对象凑在一起,可以对这些对象进行一些操作,这样形成的数据结构就是抽象数据类型。一堆的Integer在一起,无论是按列表排开,还是键值对形式存储形成一个集合,在这个集合上可以进行一些添加、删除、查找等的一些操作。这样的组织方式是ADT。
常见ADT有表、栈、队列、Map、图、树等。常见操作有添加、删除、查找、合并、包含。

列表

概念:A0,A1,A2……An1 这样的形式称为表,表的大小是n。
空表:列表中没有一个元素是空表。
前驱后继:A0A1的前驱,A1A0的后继。
位置:Ai1在列表的第i位。

实现方式

列表实现方式有数组和链表,对应Java中的ArrayList和LinkedList。一般使用双链表实现表。

基本操作

Java的Collection是ADT的基类,包含的操作有。

public interface Collection<E> extends Iterable<E> {    int size();    boolean isEmpty();    void clear();    void add(AnyType x);    boolean contains(AnyType x);    boolean remove(AnyType x);    Iterator<AnyType> iterator();}

Iterator接口

public interface Iterator<E> {   boolean hasNext();   E next();   void remove();}

Iterator接口每次对next的调用都给出集合的下一项。第1次调用next,得到第1项A0,第2次调用next,得到第2项A1……. hasNext 返回是否存在下一项。

当编译器见到一个正在用于Iterable对象增强for循环的时候,它调用iterator方法得到一个Iterator对象,然后调用hasNext和next。

对代码:

public static <T>  void print(Collection<T> coll){    for(T item : coll){        System.out.println(item);    }}

编译器改写为:

public static <T>  void print(Collection<T> coll){    Iterator<T> iterator = coll.iterator();    while(iterator.hasNext()){        System.out.println(iterator.next());    }}

Iterator的remove

Collection有remove,Iterator也有remove。Iterator的remove方法有两个优点。
1 Collection的remove需要先找到元素位置,再删除;Iterator的remove是在一边遍历过程中一边删除的。效率更高。
2 当正在迭代一个Iterator的时候,不能改变集合的结构(add,remove,clear),否则会报错ConcurrentModificationException。使用Iterator自己的remove方法则不会报错。

表的所有操作

    int size();    boolean isEmpty();    boolean contains(Object o);       boolean add(E e);    void add(int index, E element);    boolean remove(Object o);    E remove(int index);    void clear();    E get(int index);    E set(int index, E element);    Iterator<E> iterator();    ListIterator<E> listIterator();

数组与链表实现分析

场景 数组 链表 备注 set O(1) 麻烦 get O(1) 麻烦 add(int index, E element) 麻烦 O(1) 在末端添加数据 O(1) O(1) remove 麻烦 O(1) 在表的两端操作比较方便

求和场景

public static int sum(List<Integer> lst){    int total = 0;    int n = lst.size();    for(int i=0;i<n;i++){        total += lst.get(i);    }    return total;}

ArrayList (数组)运行时间O(n)。LinkedList(链表)运行时间是O(n2),因为每次get操作为O(n)。如果代码改为迭代器,计算时间都是O(n)。这个概念是我之前没有的,看到这里,想起自己以前写的代码,一身冷汗。

public static int sum(List<Integer> lst){    int total = 0;    for(Integer val : lst){        total += val;    }    return total;}

Iterator remove方法的大用处
例题:删除列表中的偶数。例如 nums={2,3,4,5,6,7},返回nums={3,5,7}。

public static void removeEvensVer1(List<Integer> lst){    int i =0;    while(i<lst.size()){        if(lst.get(i)%2==0)            lst.remove(i);        else             i++;    }}

从上表分析得知,ArrayList时间复杂度O(n2),remove比较耗时。LinkedList时间复杂度O(n3),get操作麻烦,当remove的时候,到达位置i也低效。

public static void removeEvensVer2(List<Integer> lst){    Iterator<Integer> itr = lst.iterator();    while(itr.hasNext()){        if(itr.next()%2==0)            itr.remove();    }}

使用迭代器的remove方法直接删除当前项,程序时间复杂度O(n)。

代码任务

ArrayList类的实现

LinkedList类的实现

0 0