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

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

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

线性表——顺序实现java

线性结构的特点:在数据元素的非空有限集中,(1)存在唯一第一个被称作“第一个”的数据元素;(2)存在唯一的一个被称作“最后一个”的数据元素;(3)除第一个之外,集合中的每个数据元素均只有一个前去;(4...

《Java数据结构和算法》第二版 Robert lafore 编程作业 第三章

《Java数据结构和算法》第二版 Robert lafore  编程作业 第三章 /* 3.1 bubbleSort.java程序(清单3.1)和BubbleSort专题applet中,in索...
  • zhch152
  • zhch152
  • 2012年08月25日 09:31
  • 4953

查询字符串中字母的个数(两种实现方式1,list与set集合 2,map集合)

题目: 取出一个字符串中字母出现的次数。如:字符串:"abcde%^kka27qoq" ,输出格式为:a(2)b(1)k(2)... 第一种方式(set和list结合使用): package ith...

Skip list -- 跳跃表的插入删除搜索等ADT操作的实现与测试

源代码如下: #include #include #define lgNmax 5 typedef char Key; struct Item{Key key;}; typede...

将List转成树的两种方式(递归、循环)

在做目录树的时候通常是将一个目录存在数据库的List全部返回来,再根据节点id和parentId组装成一颗树,这里切忌使用递归查询的方式实现。List转成Tree有两种方式,一种是常用的递归,一种是双...

Collections.sort方法对list的两种排序方式

Collections.sort方法对list的两种排序方式 Collections.sort( )分为两种,一种方式是排序规则,另一种方式是排序算法 。 其中规则是用来判断对象而算法...

List对象转成Gson字符串(两种方式)

List对象转成Gson字符串(两种方式) (1)使用Gson gson=new Gson()类中的  gson.toJson(list);方法 案例 (ajax+json+jquery 省市...

List集合中两种遍历方式

遍历List集合中的元素的方法有两种: 第一种:利用迭代器遍历 代码1: // 迭代器 Iterator it=list.iterator(); while(it.hasNext()) {...

【ionic+angularjs】$ionicScrollDelegate list列表行记录定位的两种方式

为什么要定位? 在访问带有列表的页面,一般会点击列表中某行记录,访问其详情页面,点击返回后回到列表页面,若不进行定位,那么用户需要重新滚动直到找到刚才点击的行记录,体验不好。那么返回时定位可以将...
  • MCpang
  • MCpang
  • 2017年02月14日 17:38
  • 358
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:List ADT的两种实现方式
举报原因:
原因补充:

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