原文连接地址
java
最近在看数据结构,发现这个东西不错,记录下来,以便分享!
ArrayList内部是使用可増长数组实现的,因此是用get和set方法是花费常数时间的,可是若是插入元素和删除元素,除非插入和删除的位置都在表末尾,不然代码开销会很大,由于里面须要数组的移动。
LinkedList是使用双链表实现的,因此get会很是消耗资源,除非位置离头部很近。可是插入和删除元素花费常数时间。
咱们来看下面一个例子:
public void listTest1(List<Integer> list, int n) {
list.clear();
for (int i=0; i<n; i++) {
list.add(i);
}
}
上面这个例子,不管是ArrayList仍是LinkedList运行的时间都是O(N),由于每次的操做都是在表末尾进行的。若是咱们把add方法换成下面的呢!
list.add(0, i);
该完以后,对于LinkedList运行时间是O(N),可是对于ArrayList则是O(N^2),一位每次添加都须要移动数组,运行时间是O(N)
再看看下面的这个例子:计算list中数据之和
public int listSum(List<Integer> list) {
int sum = 0;
for (int i=0; i<list.size(); i++) {
sum += list.get(i);
}
return sum;
}
这个例子对于ArrayList运行时间是O(N),可是对于LinkedList运行时间就是O(N^2),可是若是咱们使用加强for循环,那么就会不同。代码以下:
public int listSum2(List<Integer> list) {
int sum = 0;
for (Integer i: list) {
sum += i;
}
return sum;
}
这样不管是ArrayList和LinkedList其运行时间都是O(N),由于迭代器会有效的从一项到下一项推动。
下面咱们说一个remove方法
问题:将一个表中的全部偶数项所有删除,要求不能建立新表。
最简单的就是,进行for遍历,而后取出数值判断是不是偶数,若是是就删除,代码以下:
public static void removeEvensOne(List<Integer> list) {
for (int i=0; i<list.size(); i++) {
if (list.get(i) % 2 == 0) {
list.remove(i); //移除的是i位置上的元素
}
}
}
咱们来分析一下,若是传入的参数是Arraylist,那么效率必定会很低,我作了一下测试,建立一个400000项的ArrayList,程序运行时间大约是16s。想着若是传入的是LinkedList是否会很快,答案是否!对于LinkedList运行时间至少要一分多钟,这就奇怪了LinkedList不是删除操做是常数时间吗。咱们仔细看看这里面需最消耗时间的是list.get(i)和list.remove(i),首先对于LinkedList的get()操做时间复杂度是O(N),对于remove(i)时间,LinkedList须要到达位置i,那么如何到达,只能是从第一个元素一直搜索下去,其时间复杂读也是O(N),因此对于这个程序LinkedList消耗的时间要比ArrayList多的多。
既然用for循环须要.get(i),那咱们使用加强for循环好了,代码以下:
public static void removeEvensThree(List<Integer> list) {
for (Integer i: list) {
if (i%2 == 0) {
list.remove(i); //移除的是元素i
}
}
}
运行一下,抛出异常java.util.ConcurrentModificationException。也就是说list.remove()破坏了加强for循环,这个方法不行,可是它给了咱们一个思路:在迭代器找到一个偶数时,咱们可使用迭代器来删除这个偶数值。咱们使用Iterator迭代器,代码以下:
public static void removeEvensTwo(List<Integer> list) {
Iterator<Integer> it = list.iterator();
while (it.hasNext()) {
if (it.next() % 2 == 0) {
it.remove();
}
}
}
这个代码中咱们不须要查找,仍是使用400000个元素的list进行测试,ArrayList没有什么变化,时间依然是16s,这是由于即便迭代器位于要删除的节点上,删除以后元素仍是要移动。对于LinkedList花费的时间小于1s。
从上面咱们能够看出:ArrayList虽然get和set快,可是remove却很慢。对于LinkedList虽然删除和插入很快,可是若是期间使用了get那么同样会很慢。若是是有大量的删除操做咱们仍是使用Iterator迭代器比较好。数组
原文地址http://www.exceptionhelp.com
数据结构