算法学习之一维数据结构(one-dimentional data structure)

211 阅读3分钟

一维数据结构(one-dimentional data structure)

数组(Array)

  • 数据存储方式(Memory Controller)
    • 一般的静态语言,是通过在内存中开辟连续的内存空间按顺序存储数组的每一项。
    • 对于动态语言,例如JS,数组在内存中的存储方式是通过哈希表的方式存储的,不是选择一块连续的内存空间。所有JS的数组在插入,删除的操作相对而言更快,但是查询操作就相对比较慢了。哈希表学习之后要修正(再具体点)

常见操作的时间复杂度 | 操作方式 | prepend | append | Insert | delete | lookup | | :-----| ----: | -----: | -----:| -----:| -----:| | 时间复杂度 | O(n)/O(1) | O(1) | O(n) | O(n) | O(1) |

  • prepend是可以通过特殊办法优化至O(1)的,具体方法就是在Array开辟内存的时候,在头的位置预留一部分内存,这样再存储的时候,时间复杂度就是O(1)。
  • lookup指的是获取到某一项的值,那么对于数组而言,由于有下标的存在,所以在查找的时候,时间复杂度就是O(1)了。

链表(Linked list)

单向链表

  • 原理
  • append
  • prepend
  • insert
  • delete
  • lookup

双向链表

  • 原理
  • append
  • prepend
  • insert
  • delete
  • lookup

循环链表

  • 原理
  • append
  • prepend
  • insert
  • delete
  • lookup

常见操作的时间复杂度 | 操作方式 | prepend | append | Insert | delete | lookup | | :-----| ----: | -----: | -----:| -----:| -----:| | 时间复杂度 | O(1) | O(1) | O(1) | O(1) | O(n) |

  • 基本没什么疑问。

跳表(Skip list)

  • 特点 **只能用于元素有序的情况 **
    • 总体思想就是通过将一维链表,增加附加条件(多级索引)的方式来实现更快速的查找方式。具体方式就是使用一定的粒度来提升链表间隔,假设链表是有100有序的元素,以每5个作为一级的粒度,那么对应的第一级索引就是以(0,4,9....)为间隔,然后在以5个作为一级的粒度,那么第二级索引就是以(0, 19,39....)为间隔,之后的索引也都是以5为粒度区分,直至不能再分解下去为止。
    • 所以,接上边的例子,如果要查询一个51的元素位置,那么它的链式查询关系就是0->39->49->50->51。
  • 时间复杂度的计算
    1. n/5, n/25, n/125...第m层索引的个数就是n/5^m。
    2. 最高层的索引节点个数为k个,有m级索引,区分粒度为z,元素个数为n。那么k = n/z^m。实际查找结果的时间复杂度为:O(m) + O(z) => O(logz(n/k)) + O(z) => O(logn)
  • 空间复杂度的计算
    • n/z, n/z^1, n/z^2......求和之后n(1/z + 1/z^1 ...) ~ n,所以整体的空间复杂度为O(n)
  • 现实中的跳表的形态
    • 再增加和删除节点的时候,会打乱之前的节点。维护成本较高。
  • 实际应用
    • LRU缓存算法
    • Radis

练习