关闭

List ADT的两种实现方式

标签: 链表linkedlistarraylistadt
224人阅读 评论(0) 收藏 举报
分类:

ArrayList类和LinkedList类

List ADT 有两种流行的实现方式,ArrayList类与LinkedList类。

ArrayList类提供了List ADT 的一种可增长数组的实现。使用ArrayList的优点在于,对get和set的调用花费常数时间。缺点是对于新项的插入和现有项的删除代价昂贵。除非更改是发生在末端的。

LinkedList类则提供了List ADT 的双向链表的实现。使用LinkedList的优点在于,新项的插入和现有项的删除开销很小,缺点则是get和set的开销很大,除非接近端点。

下面用一些方法来使结论更明显:

public static void makeList(List<Integer> lst, int N) {
    lst.clear();
    for (int i = 0; i < N; i++) {
        lst.add(i);
    }
}
Type Time
ArrayList O(N)
LinkedList O(N)

无论ArrayList还是LinkedList,每次调用add都是在表的末端进行,所以都是O(N)


public static void add(List<Integer> lst, int N) {
    lst.clear();
    for (int i = 0; i < N; i++) {
        lst.add(0, i);
    }
}
Type Time
ArrayList O(N2)
LinkedList O(N)

public static int sum(List<Integer> lst, int N) {
    int total = 0;
    for (int i = 0; i < N; i++) {
        total += lst.get(i);
    }
    return total;
}
Type Time
ArrayList O(N)
LinkedList O(N2)

这里特别要说明下的是,如果改用增强for循环,那么两者的时间就都是O(N),因为迭代器将有效地从一项到下一项推进。

迭代器

作为一个例子,我们提供一个例程,将一个表中所有具有偶数值的项删除。

当遇到表中的项时,将其从表中删除的算法有几种可能的想法,当然我们有兴趣的是写一个干净的避免拷贝的表,并在遇到偶数值时就将它们删除。

对于ArrayList这就是一个失败的策略,因为对ArrayList的任意一个地方进行删除都是效率很低的,但在LinkedList中却有希望,因为从已知位置删除项可以通过修改链而完成。

想法1:

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上,remove的效率是很低的,程序的花费是二次时间。
在LinkedList上,由于对get调用效率的不高(每次寻找都得从两端开始),所以程序的花费是二次时间。

想法2:

public static void removeEvenVer2(List<Integer> lst) {
    for (Integer x : lst) {
        if (x % 2 == 0) {
            lst.remove(x);
        }
    }
}

这个想法试图矫正上一种思路,不再使用get而是用iterator遍历表,这显然是高效率的。但是使用了Collection的remove方法,会抛出一个异常。
想法3:

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

这是一个成功的想法,对于一个LinkedList,迭代器的remove方法的时间花费是线性的,因为迭代器位于被删除的节点上,而对于ArrayList,始终要在remove后进行数组的移动,仍然花费二次时间。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:1390次
    • 积分:122
    • 等级:
    • 排名:千里之外
    • 原创:11篇
    • 转载:1篇
    • 译文:0篇
    • 评论:0条