既然有了数组,那么链表到底有何存在意义?

z1246879396 2016-11-08 07:34:01
数组的查询是比链表要快很多倍的,
而数组的插入删除比链表要慢很多,
这些大家都知道,
那么,链表可以用作频繁的插入删除,
但是链表插入删除一个,数组插入删除一个时间复杂度都是一样的(中间插入)
应用中难道有一次性插入十个元素,或者一次性删除10个元素?
大多数还都是删除插入一个元素的。
并且,链表中存放的数据,我们要使用的话,肯定离不开查询。
那么链表究竟在什么样的场景中会使用呢?
跪求大神赐教!
...全文
433 10 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
z1246879396 2016-11-09
  • 打赏
  • 举报
回复
引用 2 楼 bree06 的回复:
为何你认为数组插入删除一个元素时间复杂度和链表相同呢? 除了在尾部追加元素不需要移动其他元素外, 在任意地方地方插入删除都需要移动当前~未尾的位置. 如果在第0的位置插入一个元素的话需要将原数组整个向后移动一遍. 数组是定长的, 如果超过长度必须重新分配更大的空间, 然后把当前数据移动到新数组中. 链表就没有这个烦恼. 我们知道数组的空间都是连续分配的. 在以前内存非常有限的情况下连续分配一块很大的空间非常困难的. 就算现在内存8G,16G时代要连续分配一个10亿长度的空间也需要较长时间的.而且如果内存中没有更大块连续存储空间将导致分配失败; 另外长度未知情况下的实现比如ArrayList会造成一写的空间浪费. JDK1.7, 1.8的增长因子都是n/2. 例如现在长度为100, 我要存第101个元素, 那ArrayList会扩容到150. 那就使得49个空间浪费了. 链表更适合在长度难以估计内存空间紧张, 长度较大, 插入删除频繁, 查询搜索较少的场景. 但是整体来说ArrayList的应用场景要大于链表. 假写事先不知道总长度.下面是1千万长度的数组和链表插入和删除操作测试.
public static void main(String[] args) {
    List<Integer> list = new ArrayList<>(); // 3764/80
//    List<Integer> list = new LinkedList<>(); // 6835/15
    long start = System.currentTimeMillis();
    for (int i = 0; i < 10000000; i++) { // 1千万
        list.add(i);
    }
    System.out.println(System.currentTimeMillis() - start);
    start = System.currentTimeMillis();
    list.remove(10);
    list.add(1, 0);
    list.add(10, 0);
    list.add(100, 0);
    list.remove(10000);
    list.add(1000, 0);
    list.remove(1);
    list.add(10000, 0);
    list.add(100000, 0);
    list.remove(100000);
    list.add(1000000, 0);
    list.remove(100);
    list.remove(1000);
    list.remove(1000000);
    System.out.println(System.currentTimeMillis() - start);
}
首先,很感谢大神的讲解,那么如果这个1000万的链表存放的数据,我后期需要从其中查询某个是否存在,就好比,我随机生成一个6位的验证码,然后,我为了测试多久之后,这个验证码会重复,我会把每次产生的验证码先放到一个无序数组(Arraylist),然后遍历查询,这个我监控过jvm内存,的确会呈现1/2增长,链表是很平缓的,但是计算出结果的速度数组不知道快了多少倍。所以,主要还是,链表放进去容易,具体使用其中的数据的场景有哪些? 还望大神耐心解答~
nikyotensai 2016-11-09
  • 打赏
  • 举报
回复
引用 2 楼 bree06 的回复:
为何你认为数组插入删除一个元素时间复杂度和链表相同呢? 除了在尾部追加元素不需要移动其他元素外, 在任意地方地方插入删除都需要移动当前~未尾的位置. 如果在第0的位置插入一个元素的话需要将原数组整个向后移动一遍. 数组是定长的, 如果超过长度必须重新分配更大的空间, 然后把当前数据移动到新数组中. 链表就没有这个烦恼. 我们知道数组的空间都是连续分配的. 在以前内存非常有限的情况下连续分配一块很大的空间非常困难的. 就算现在内存8G,16G时代要连续分配一个10亿长度的空间也需要较长时间的.而且如果内存中没有更大块连续存储空间将导致分配失败; 另外长度未知情况下的实现比如ArrayList会造成一写的空间浪费. JDK1.7, 1.8的增长因子都是n/2. 例如现在长度为100, 我要存第101个元素, 那ArrayList会扩容到150. 那就使得49个空间浪费了. 链表更适合在长度难以估计内存空间紧张, 长度较大, 插入删除频繁, 查询搜索较少的场景. 但是整体来说ArrayList的应用场景要大于链表. 假写事先不知道总长度.下面是1千万长度的数组和链表插入和删除操作测试.
public static void main(String[] args) {
    List<Integer> list = new ArrayList<>(); // 3764/80
//    List<Integer> list = new LinkedList<>(); // 6835/15
    long start = System.currentTimeMillis();
    for (int i = 0; i < 10000000; i++) { // 1千万
        list.add(i);
    }
    System.out.println(System.currentTimeMillis() - start);
    start = System.currentTimeMillis();
    list.remove(10);
    list.add(1, 0);
    list.add(10, 0);
    list.add(100, 0);
    list.remove(10000);
    list.add(1000, 0);
    list.remove(1);
    list.add(10000, 0);
    list.add(100000, 0);
    list.remove(100000);
    list.add(1000000, 0);
    list.remove(100);
    list.remove(1000);
    list.remove(1000000);
    System.out.println(System.currentTimeMillis() - start);
}
bree06 2016-11-09
  • 打赏
  • 举报
回复
为何你认为数组插入删除一个元素时间复杂度和链表相同呢? 除了在尾部追加元素不需要移动其他元素外, 在任意地方地方插入删除都需要移动当前~未尾的位置. 如果在第0的位置插入一个元素的话需要将原数组整个向后移动一遍. 数组是定长的, 如果超过长度必须重新分配更大的空间, 然后把当前数据移动到新数组中. 链表就没有这个烦恼. 我们知道数组的空间都是连续分配的. 在以前内存非常有限的情况下连续分配一块很大的空间非常困难的. 就算现在内存8G,16G时代要连续分配一个10亿长度的空间也需要较长时间的.而且如果内存中没有更大块连续存储空间将导致分配失败; 另外长度未知情况下的实现比如ArrayList会造成一写的空间浪费. JDK1.7, 1.8的增长因子都是n/2. 例如现在长度为100, 我要存第101个元素, 那ArrayList会扩容到150. 那就使得49个空间浪费了. 链表更适合在长度难以估计内存空间紧张, 长度较大, 插入删除频繁, 查询搜索较少的场景. 但是整体来说ArrayList的应用场景要大于链表. 假写事先不知道总长度.下面是1千万长度的数组和链表插入和删除操作测试.
public static void main(String[] args) {
    List<Integer> list = new ArrayList<>(); // 3764/80
//    List<Integer> list = new LinkedList<>(); // 6835/15
    long start = System.currentTimeMillis();
    for (int i = 0; i < 10000000; i++) { // 1千万
        list.add(i);
    }
    System.out.println(System.currentTimeMillis() - start);
    start = System.currentTimeMillis();
    list.remove(10);
    list.add(1, 0);
    list.add(10, 0);
    list.add(100, 0);
    list.remove(10000);
    list.add(1000, 0);
    list.remove(1);
    list.add(10000, 0);
    list.add(100000, 0);
    list.remove(100000);
    list.add(1000000, 0);
    list.remove(100);
    list.remove(1000);
    list.remove(1000000);
    System.out.println(System.currentTimeMillis() - start);
}
ps45221 2016-11-09
  • 打赏
  • 举报
回复
首先你没用到并不代表它没有用处,最常见的用途就是Hash表,Java中hashmap的实现,解决冲突的方法就是链表。 再者,只考虑java的层面,数组的删除和添加,我印象中,是拷贝到一个新数组中的,而链表就只需分配 / 解绑这个指向就可以了。
bree06 2016-11-09
  • 打赏
  • 举报
回复
引用 9 楼 z1246879396 的回复:
引用 7 楼 bree06 的回复:
[quote=引用 4 楼 z1246879396 的回复:]
[quote=引用 2 楼 bree06 的回复:]
.
刚才忘了传图了
z1246879396 2016-11-09
  • 打赏
  • 举报
回复
引用 7 楼 bree06 的回复:
[quote=引用 4 楼 z1246879396 的回复:] [quote=引用 2 楼 bree06 的回复:] 链表放进去容易,具体使用其中的数据的场景有哪些? 还望大神耐心解答~
一个明显的场景是队列, 双向队列. 这个在作业算法中更常见, 比如写一个症所的排队系统, 候症所区的位置是有限的假设10个位置, 按照先来先就医的原则. 用数组和链表的不同表现方式大概是如下方式. 数组: 第1个人就医后从第2个人开始依次向前移动. 候症区外的一个人进入第10位. 如此反复. (相当于排队) 链表: 第1个人就医后, 候症区外的某一人拿到排队号等到第10个位置后面. 其它人不用移动. (相当于取号) 因为这里不需要查找和遍历所以链表更加的适合场景. 而数组需要反复的移动. 你可以尝试写一个作业系统. C++ STL中的list, queue和deque 均是用链表实现.[/quote] 谢谢大神,大学学的太渣了,在队列中链表的确是很方便的。看看作业调度和队列去。感谢
z1246879396 2016-11-09
  • 打赏
  • 举报
回复
引用 5 楼 nicky918 的回复:
而数组的插入删除比链表要慢很多, 这些大家都知道, 我不知道这句,学习了
Sorry,这个帖子说的也很有道理,真的动手做实验了才会很诧异。 http://blog.csdn.net/qq_21544879/article/details/51909473
bree06 2016-11-09
  • 打赏
  • 举报
回复
引用 4 楼 z1246879396 的回复:
[quote=引用 2 楼 bree06 的回复:] 链表放进去容易,具体使用其中的数据的场景有哪些? 还望大神耐心解答~
一个明显的场景是队列, 双向队列. 这个在作业算法中更常见, 比如写一个症所的排队系统, 候症所区的位置是有限的假设10个位置, 按照先来先就医的原则. 用数组和链表的不同表现方式大概是如下方式. 数组: 第1个人就医后从第2个人开始依次向前移动. 候症区外的一个人进入第10位. 如此反复. (相当于排队) 链表: 第1个人就医后, 候症区外的某一人拿到排队号等到第10个位置后面. 其它人不用移动. (相当于取号) 因为这里不需要查找和遍历所以链表更加的适合场景. 而数组需要反复的移动. 你可以尝试写一个作业系统. C++ STL中的list, queue和deque 均是用链表实现.
z1246879396 2016-11-09
  • 打赏
  • 举报
回复
引用 5 楼 nicky918 的回复:
而数组的插入删除比链表要慢很多, 这些大家都知道, 我不知道这句,学习了
不好意思,这个没有深入想就说了出来,应该是原理上方便很多。插入一个数据的时候,数组和链表应该是一样的时间复杂度。10000长度的数组链表,插在其中一位(指中间),数组是直接移位到目的处,然后剩下的元素后移一位。链表应该是先去查找到这个目的地,然后插入。所以数组的时间用来后移数据,链表的用来查找位置。(我也只是个菜鸟,想深入了解才和大家讨论) http://blog.chinaunix.net/uid-20443874-id-1945891.html
汤圆甜筒 2016-11-09
  • 打赏
  • 举报
回复
而数组的插入删除比链表要慢很多, 这些大家都知道, 我不知道这句,学习了

62,635

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧