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

抽象数据类型 ADT

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

列表

概念: A0 , A1 , A2 …… An1 这样的形式称为表,表的大小是n。
空表:列表中没有一个元素是空表。
前驱后继: A0 A1 的前驱, A1 A0 的后继。
位置: 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();

数组与链表实现分析

场景数组链表备注
setO(1)麻烦
getO(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类的实现

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值