数组和链表的实例讲解——以Facebook为例

数组支持随机访问,而链表只能顺序访问。那在实际使用中什么样的场合下该使用数组,或者链表呢?

  • 1、假设你要编写一个记账的应用程序。包含买杂货、看电影和交会费。你每天都将记录所有的支出,并在月底统计支出,算算当月花了多少钱。因此,你执行的插入操作很多,读取操作很少,该使用数组还是链表呢?
  • Ans:实际上每天都要添加支出项,月底读取支出一次。数组的读取速度快,插入速度慢;而链表的读取速度慢,插入速度快。由于执行的插入操作次数多于读取操作,因此使用链表更为合适。另外,仅当你随机读取数据时,链表的访问速度才慢。鉴于要读取所有的数据,因此链表的速度并不慢。因此对于这个问题,使用链表很不错。

下面是数组和链表常见操作的复杂度:

操作数组链表
插入O(n)O(1)
读取O(1)O(n)
删除O(n)O(1)

Q1:每当你登录Facebook时,FB都会查找你填写的用户名,如果找到则允许登录。因此FB需要执行大量的用户名查找操作。假设FB采用二分查找算法,而这种算法要求能够随机访问——立即获取中间的用户名。考虑到这一点,应使用数组还是链表存储用户名?

Ans:随机访问显然是数组。

Q2:经常有用户会在FB注册。假设你已经决定使用数组来存储用户名,在插入方面数组有何缺点呢?具体滴说,在数组中添加新用户将出现什么情况?

Ans:数组的插入速度很慢,复杂度为O(n)。另外采用二分查找必须之前就进行排序,因此每注册一个用户就需要重新排序,时间开销极大。

Q3:实际上,FB存储用户信息时使用的既不是数组又不是链表。假设FB使用的是一种混合数据:链表数组。在这个数组中包含26个元素,每个元素都指向一个链表。例如,该数组的第一个元素指向的链表包含以A开头的用户名,该数组的第二个元素指向的链表包含以B开头的用户名……如下图所示:

假设Adit B在FB注册,而你需要将其加入前述数据结构中。因此,你访问数组的第一个元素,再访问该元素指向的链表,并将Adit B添加到这个链表的结尾。现在假设你要查找Zak H。因此你访问第26个元素,再在它指向的链表中查找Zak H。

请问,相比于数组和链表,这种混合数据结构的插入和查找速度是否更快?

Ans:查找时,其速度比数组慢,但比链表快;而插入时,与链表相当,比数组快。因此,其查找速度比数组慢,但在各方面都不比链表慢。这种混合的链表数组实际上是散列表的一个例子。

FB实际上使用的是什么呢?很可能是十多个数据库,他们基于众多不同的数据结构:散列表、B数等。数组和链表是这些高级数据结构的基石。


总结:

数组的缺点就在于插入的时间复杂度较大,读取速度较快,如果只插入不排序,会导致查找的复杂度增大;而链表的缺点就在于不能随机访问,也就是读取的速度较慢。但是插入和排序较快。链表数组是它们两者的结合,具有了两者的优点,但也不是最理想的。

 

内容整理自Aditya Bhargava《算法图解》

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吉大秦少游

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值