各种数据结构的时间复杂度分析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chao2016/article/details/82425317

对于同一个数据结构来说,底层实现的不同往往会呈现出不同的时间复杂度。以数组为例:

. 普通数组实现 顺序数组实现 二分搜索树(平衡)
插入 O(1) O(n) O(logn)
查找 O(n) O(logn) O(logn)
删除 O(n) O(n) O(logn)

1. 动态数组

对于一个基于Java E[]实现的动态数组Array来说,它的时间复杂度如下:

  • 增:O(n)
  • 删:O(n)
  • 改:已知索引 O(1);未知索引 O(n)
  • 查:已知索引 O(1);未知索引 O(n)
  • resize:通过均摊复杂度分析得 O(1)

2. 数组栈

对于一个基于动态数组Array实现的数组栈ArrayStack来说,它的时间复杂度如下:

  • void push(E): O(1) 均摊
  • E pop(): O(1) 均摊
  • E peek(): O(1)
  • int getSize(): O(1)
  • boolean isEmpty(): O(1)

3. 数组队列

对于一个基于动态数组Array实现的数组队列ArrayQueue来说,它的时间复杂度如下:

  • void enqueue(E): O(1) 均摊
  • E dequeue(): O(n)
  • E front(): O(1)
  • int getSize(): O(1)
  • boolean isEmpty(): O(1)

4. 循环数组队列

对于一个基于Java E[]实现的循环队列LoopQueue来说,它的时间复杂度如下:

  • void enqueue(E): O(1) 均摊
  • E dequeue(): O(1) 均摊
  • E front(): O(1)
  • int getSize(): O(1)
  • boolean isEmpty(): O(1)

数组和链表

数组最大的优点:支持随机访问、快速查询。
数组最好用于索引有语义的情况。

链表最大的优点:动态。
链表不适合用于索引有语义的情况。

5. 链表

  • 增:O(n)
  • 删:O(n)
  • 改:O(n)
  • 查:O(n)

链表不适合修改操作;
如果只对链表头进行增删查操作:O(1)

6. 链表栈

  • 与数组栈各操作的时间复杂度上是同一量级 O(1)。
  • 时间上的差异可能在于:数组栈在分配空间方面;链表栈在new寻找内存空间方面。

7. 链表队列

  • 与数组队列各操作的时间复杂度上是同一量级 O(1)。
  • 特别的,链表的head容易做增、删操作,而tail只容易做增操作,故tail端入队,head端出队。

链表是天然的递归结构。递归调用是有代价的:函数调用+系统栈空间。
递归函数的调试:添加一个递归深度变量depth作为函数参数。

8. 双链表

9. 循环链表

10. 数组链表

11. 集合

. LinkedListSet BSTreeSet BSTreeSet最优 BSTreeSet最差
增add O(n) O(h) O(logn) O(n)
查contains O(n) O(h) O(logn) O(n)
删remove O(n) O(h) O(logn) O(n)

基于搜索树的实现:有序集合
基于哈希表的实现:无序集合

多重集合:集合中的元素可以重复

猜你喜欢

转载自blog.csdn.net/chao2016/article/details/82425317