数据结构
数据结构的性状大致有两种,线形数据结构和树形数据结构。
链表
链表是线形的数据结构,有三种分类:单链表、双链表、循环链表。
单链表
单链表有以下特性:
-
除了最后一个数据之外,其他数据都有一个指针,指向下一个数据的内存地址。
-
插入、删除数据方便,但是访问数据困难。
-
分散储存在内存中,如下图所示。
数据插入步骤(将 Green 插到 Blue 之后):
- 将 Blue 的指针指向 Green 的内存地址。
- 将 Green 的指针指向 Yellow 的内存地址。
数据删除步骤(删除 Yellow):
- 将 Blue 的指针指向 Red 。
数据访问步骤(访问 Red):
- 从链表头部,开始查询,先匹配 Blue 和 Red,发现不是要找的数据,根据 Blue 的指针找到下一个数据 Yellow 。
- 匹配 Yellow ,发现不匹配,根据 Yellow 的指针找到下一个数据 Red 。
- 匹配 Red,找到数据。
时间复杂度分析:
- 插入和删除操作只需要改变指针的指向,时间复杂度为 O(1)
- 访问数据与链表的长度 n 有关,为O(n)
双链表
双链表插入、删除、访问步骤和单链表一样,只不过修改指针的指向需要修改两个方向的指针。
访问数据不同于单链表,只能从前往后遍历数据,双链表可以从后往前遍历数据。
双链表访问数据可以双向遍历,更加方便,但是双向指针会耗费更多的储存空间,并且插入删除需要改变更多的指针的指向。
循环链表
单链表最后一个数据的指针指向链表的头部,就构成了循环链表,循环链表没有头尾的概念。
数组
数组也是线形数据结构,不同于链表,数组访问数据非常方便,但是数据的插入和删除比较繁琐。
数组概念图如下所示:
并且数组里面的数据是连续存储在内存中,如下图所示:
[]
中的数字表示该数据在数组中的第几个位置,每个数据有位置标记,访问自然非常简单(随机访问)。
插入数据步骤:
- 在数组末尾增加储存空间。
- 先将该位置和之后的所有数据往后移动一位,腾出位置。
- 将数据插入空位。
删除数据步骤:
- 将数据删除。
- 把该数据之后的所有数据往前移动一位来填充这个空位。
- 删除末尾多出来的储存空间。
时间复杂度分析:
- 访问由于数组在内存中连续储存,可以计算出每个数据的位置,直接一步访问,时间复杂度为O(1) 。
- 插入与删除数据的时间复杂度与数据的长度 n 和要插入、删除的位置有关,在头部进行插入、删除操作,需要移动 n 次数据,在尾部进行插入、删除操作,不需要移动数据。因此时间复杂度为O(n)