# 部分摘自《算法图解》,转载请留言联系
有时候,需要在内存中存储一系列的元素。假设你要编写一个管理待办事件的程序,你需要把这些管理待办事件储存在内存中。
用数组和链表分别是怎么存储这些数据的呢?
-
数组
数组意味着所有待办事件在内存中都是相连的(紧靠在一起的)。例如内存有16个格子,你的待办事件有3件,那么他们要放在一起,就像你和你的2个朋友去电影院看电影一样,坐在一起。
x | x | x | x | x | 待办事件1 | 待办事件2 | 待办事件3 | x | x |
数组的存储只能放在一起的。这样有什么优点与缺点呢?
优点:我们记录了待办事件1的位置是5,那么我们可以很快的知道待办事件3的位置是7。这就是数组的优点,可以迅速找到数组的任何元素。查找的复杂度是O(1),也就是我们根据初始位置的值,可以一次就查询出指定位置的值。所以数组的查询速度快。
缺点:假如你又有一个新增的待办事件,当然,需要在待办事件3之后插入。但是如上面的内存表格所示,待办事件3后面的内存单元已经被占据了。所以它只能找另外一个地方,能放下4个待办事件的,把全部的待办事件移过去。如下面的内存表格所示:
x | x | x | x | x | x | x | 待办事件1 | 待办事件2 | 待办事件3 | 待办事件4 |
如果以后还有新的元素插入,内存位置不够,那还得再找位置,而且全部元素都必须移动过去。所以数组的插入是很慢的。插入的复杂度是O(n)
-
链表
链表的每个元素都存储了下一个元素的地址,从而使一系列随机的内存地址串在一起。
存储格式如下:
x | 待办事件1+(待办事件2的内存地址) | x | x | x | 待办事件2+(待办事件3的内存地址) | x | 待办事件3 | x | x |
链表有什么优点与缺点呢?
优点:链表的优势在插入元素方面。在链表中,元素不需要放在一起。插入元素时,只需要将其放入内存,并将其地址存储在前一个元素中就可以了。这样的存储结构就不会像数组那么尴尬,插入新元素的时候位置不够还要全体移动。链表插入的时间复杂度是O(1)。
缺点:当你想读取链表的最后一个元素时,你不能直接读取,因为你不是它所处的地址。如你想访问待办事件3,但是你不知道它的内存地址,你要先访问待办事件1,然后取得待办事件2的地址,再访问待办事件2,取出待办事件3的地址,才能访问待办事件3。因此链表查询的时间复杂度是O(n)。
数组与链表的插入与查询说完了,接下来说下从中间插入与删除。
- 从中间插入:数组需要把插入位置后面的元素往后移,如果位置不够还要全体换位置,时间复杂度为O(n)。而链表,可以随便找个位置插入,只需要将其地址存储在前一个元素中就可以了。
- 删除:删除其实也同理。数组需要挪,链表直接删除,然后需要一个引用内存地址就可以了。数组删除的时间复杂度是O(n),链表删除的时间复杂度是O(1)。
-
数组和链表哪个用得多一点呢?
一般会有两种访问方式,随机访问和顺序访问。顺序访问意味着从第一个元素开始逐个读取元素。随机访问代表着可直接跳到第n个元素。
所以,链表只能用于顺序访问。数组都可以。
因为很多情况都要求能够随机访问,因为数组用得多一点。