谈谈数组和链表

5 篇文章 0 订阅

最近在学习Java集合这一块知识,发现编程语言不过是一门语言,底层数据结构才是核心。不得不复习起来数组和链表。可以对应于ArrayList 和 LinkedList。

看了网上很多文章都是这样说的:

ArrayList 查找速度快效率高,增删效率低;
LinedList 查找效率低下,但增删效率高。

??真的是这样吗?凡事没有绝对性,我们知道这些可能都是在对应某种情况下或者总体相对而言是这样的。

我们知道,ArrayList 底层是数组,而LinedList底层是双向链表。我们来比较两者存储结构的差别。

数组:一段连续的内存,我们通过数组的首地址可以找到数组,通过数组的索引可以快速查找某元素。

链表: 链表在内存中的地址不是连续的,由一系列结点node(链表中每一个元素称为结点)组成,结点可以在运行时i动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。

单向链表:链表中只有一条链子,不能保证元素的顺序,存储和取出元素的顺序可能不一致。

双向链表:链表中有两条链子,有一条链子是专门记录元素的顺序,是一个有序的集合。

一般来说:

数组查询快:通过数组的首地址找到数组后根据索引就可以快速找到元素,时间复杂度是O(1)。值得注意的是这里说的相当于是知道索引值去查找元素,如果是知道元素去查找,那就有可能是完全遍历了,查找效率没有那么高了。(LinkedList 在头部和尾部查找速度也是非常之快的,但是会随着向中间靠拢效率越来越低(注意后面提到的node()方法)。而ArrayList的查找效率是毋庸置疑的)

  对于数组来说,增删元素需要新建一个数组,因为数组的长度是固定的,我们需要把原来的数据复制一份,再将地址赋值给原来的引用。(在堆内存中,频繁的创建数组,复制数组中的元素,销毁数组(原数组在内存中会被销毁),效率低下!

 对Java集合中的ArrayList来说,它是一个可以扩容的数组,对它插入/删除元素,意味着所有后面的元素要向后移,这样的代价是很大的。but 如果是在尾部插入,那么使用ArrayList也可以达到很高的效率。(O(1))

  如果是在头部插入的话,效率会很低。


  相反,LinkedList在头部和尾部插入删除效率都是O(1),但是越往中间靠拢插入/删除效率会大大降低,在正中间时插入/删除的效率远远小于ArrayList。

 这是因为LinkedList 在头尾以外的位置插入元素当然得找出这个位置在哪里,我们可以通过它里面的源码看看,里面的node()方法就是关键所在,这个函数的作用就是根据索引查找元素,但是它会先判断index的位置,size右移一位相当于是除以2,相当于折半看看哪边比较进就从哪里遍历找到之后然后插入吧

    /**
     * Returns the (non-null) Node at the specified element index.
     */
    Node<E> node(int index) {
        // assert isElementIndex(index);

        if (index < (size >> 1)) {
            Node<E> x = first;
            for (int i = 0; i < index; i++)
                x = x.next;
            return x;
        } else {
            Node<E> x = last;
            for (int i = size - 1; i > index; i--)
                x = x.prev;
            return x;
        }
    }

  所以,我们大概对“ArrayList 和 LinkedList的差别”类似于"ArrayList 查找快增删慢, 和 LinkedList查找慢增删快"这么笼统的说法有了一些新的见解。

参考博文:https://juejin.im/post/5c00987de51d451aa843b67b

ps: 从这篇文章中收获很多!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值