List ADT的两种实现方式

原创 2017年01月03日 03:00:46

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后进行数组的移动,仍然花费二次时间。

版权声明:本文为博主原创文章,未经博主允许不得转载。

adt_list.txt

  • 2013年04月13日 19:11
  • 4KB
  • 下载

List ADT的两种实现方式:ArrayList和LinkedList

List ADT 有两种实现方式:ArrayList和LinkedList。现在我对这两种方式的优缺点进行了一下总结: 1.ArrayList类提供了List ADT 的一种可增长数组的实现     ...
  • u012379844
  • u012379844
  • 2017年07月18日 18:55
  • 197

List集合和LinkList的讲解

之前我们在做项目的时候,曾遇到过一个小问题:在设置适配器之后, 就是如果想让list集合进行倒叙排列或者是在做拖动listview的Item的时候,想重新改变list的顺序。尤其在做下拉刷新和上拉加载...
  • androidstarjack
  • androidstarjack
  • 2015年02月12日 15:32
  • 2267

C语言ADT(抽象数据类型编程)

C语言是一种计算机程序设计语言。它既具有高级语言的特点,又具有汇编语言的特点。它可以作为工作系统设计语言,编写系统应用程序,也可以作为应用程序设计语言,编写不依赖计算机硬件的应用程序。因此,它的应用范...
  • zhangzhi123456789
  • zhangzhi123456789
  • 2015年09月23日 13:03
  • 1968

List ADT的两种实现方式

ArrayList类和LinkedList类 List ADT 有两种流行的实现方式,ArrayList类与LinkedList类。...
  • heyahuihh
  • heyahuihh
  • 2017年01月03日 03:00
  • 927

表ADT

本文简单的介绍数据结构中表的概念,以及表在Java中的实现方式。
  • qq2430
  • qq2430
  • 2017年04月08日 14:07
  • 260

多线程实现的两种方式及其区别

继承Threadpublic class Demo2_Thread { public static void main(String[] args) { MyThread mt ...
  • StriverLi
  • StriverLi
  • 2017年02月26日 21:07
  • 1678

线性表的两种实现 -- 顺序表和链表(C++)

线性表两种实现方法的比较 空间方面: 顺序表的缺点:大小事先固定。虽然便于分配空间,但是元素只有少数的几个时造成空间的浪费。 链表的优点:只有实际在链表中的对象需要空间,只要存在可用的内存空间分...
  • y396397735
  • y396397735
  • 2016年05月27日 10:57
  • 1781

list的基本操作

list是python内置的列表对象,可以类比其他语言中的数组。python是一种解释型的语言,同样list列表中可以存放不同的数据类型,这和js,php都有相同的地方。 list的基本操作; 1.创...
  • qlzx_syzx
  • qlzx_syzx
  • 2016年10月16日 15:35
  • 307

ADT - 顺序表(Squencial List)

//ADT Squencial List #include #define TRUE 1 #define FALSE 0 #define OK 1 #define ...
  • l1832876815
  • l1832876815
  • 2017年09月25日 01:40
  • 172
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:List ADT的两种实现方式
举报原因:
原因补充:

(最多只允许输入30个字)