常用数据结构的功能及复杂度总结(OI)

烈酒焚心 提交于 2020-04-13 15:09:45

【今日推荐】:为什么一到面试就懵逼!>>>

不定长数组

维护一个序列

在末尾插入/删除均摊O(1)

任意位置插入O(n)

指定位置查询/修改O(1)

空间O(n)

链表

维护一个序列

定位到第i个位置O(n)

在任意位置(已定位到该位置)插入/删除/修改O(1)

空间O(n)

散列表

维护键-值对应关系或维护键的存在性

1.开放寻址法散列表

若已插入键个数小于表大小的3/4则可以认为查询/修改/插入期望O(1),最坏O(n)若正确选择hash函数一般不会出现

删除只能标记删除

一般所需空间应大于键个数的4/3以保证效率

2.链接法散列表

若表中键个数a,表大小n,则查询/修改/插入/删除期望O(1+a/n),最坏O(n),若正确选择hash函数一般不会出现

必要时可以用平衡树代替链表而做到最坏O(logn)但实用价值不大

维护一些元素

支持O(1)插入和弹出元素,且保证弹出的元素是栈中最后一个插入的元素

队列

维护一些元素

支持O(1)插入和弹出元素,且保证弹出的元素是队列中最先插入的元素

并查集

维护一些元素以及两两之间是否同类(同类关系可传递)并支持将两个元素所属的类合为一类

1.并查集的森林实现

按秩合并+路径压缩 查询/合并 均摊O(α(n,m))

仅按秩合并 单次操作保证O(logn)

仅路径压缩 单次操作保证O(logn)

2.并查集的链表/不定长数组/图实现

查询/合并 均摊O(logn)

支持遍历某元素所在集合

树状数组

维护一个序列

设序列长度n,操作个数m

修改指定位置元素的值O(logn)

求指定区间元素的和O(logn)

推广:

通过维护差分可以O(logn)区间增加指定值,查询元素的值

维护任意满足区间加法的运算下的前缀和 

维护任意满足区间间法的运算下的区间和

k维推广:

空间O(nk),利用散列表动态开点可做到O(mlogkn)

单次修改/k维区间和O(logkn)

平衡树

维护一个(非严格)单调序列

查询前趋后继/插入/删除O(logn)

在维护size后可支持O(logn)查询排名/小于k的元素个数

不维护序列单调性而只维护普通序列 可以支持O(logn)指定位置插入/删除/查询

splay可实现区间翻转,序列的分裂合并等操作,复杂度为均摊O(logn),treap可以在期望O(logn)做到这些操作

红黑树具有较小的期望常数,avl树则只在查询时较快

利用线段树的规则可以维护区间信息

线段树

维护一个序列的区间信息

可支持单点/区间 修改/查询,一般单次操作O(logn),要求维护的信息满足结合律

对长度为d的区间内每个点一起进行修改,复杂度为O(d+logn)

合并两棵线段树的复杂度与合并中减少的节点数相当,按某个值分裂线段树的复杂度为O(logn)

如果无修改操作,也可以O(nlogn)预处理,O(1)查询区间信息

利用类似平衡树的规则可以实现在指定位置插入/删除O(logn)

指针实现的线段树可以方便地可持久化/动态开点等

维护一些无序元素

查询最小值O(1)

插入元素/删除最小值O(logn)

(已定位到指定元素)减小指定元素的值O(logn)(斐波那契堆等为均摊O(1))

可并堆可支持O(logn)合并

字典树

维护一些串

支持O(n)插入/删除一个长度为n的串,查询一个串是否存在,查询一个串是否是某个串的前缀

也可以用于实现字典操作维护键-值对应

通常实现需要空间O(nk),k为字符集大小,n为插入的总串长

平衡树维护可只用O(n)空间但操作复杂度变为O(nlogk)

ST表

维护一个序列

构建时间空间均为O(nlogn)

查询区间最大值O(1)

最大值可换为其它任意 可由两个区间的值得出并区间的值 的运算

块状链表/块状数组

维护一个序列,相当于动态分块

指定位置查询/修改/插入/删除/区间翻转/区间查询/区间修改 O(n0.5)

分块

可以维护很多线段树和平衡树等无法高效实现的操作,时间复杂度一般是O(n0.5),必要时可为了平衡块内和块间操作的复杂度而调整这个值

利用每个块内部元素较少和总块数较少的特点,可以用较高的复杂度预处理/重构一个块的信息,要求对每个块查询的结果可以高效合并,对每个块可以整体标记修改

k-d

维护k维空间中的点 k>1

构建O(knlogn)

空间O(nk)

插入期望O(logn),如果用替罪羊树的重构规则可以保证最坏O(log2n)

查询/修改(每维指定区间)信息O(min(n,k2kn1-1/k))

查询最近/最远点/与向量最大点积/距离给定点小于定值的点期望复杂度较优,但最坏情况退化为O(n)

可持久化数据结构

一般实现方式为path copy或fat node

原数据结构有严格的时空复杂度,则可持久化后仍可保证复杂度

若原数据结构为线性数据结构则一般不能直接可持久化,复杂度可能虚要乘上一个logn

一般空间不可避免的会增大每次操作logn或更大,但不会超过时间复杂度

均摊复杂度在可持久化后一般最坏情况会退化

数据结构树上推广

通过树链剖分可将形态不变的树分解为链进行维护,复杂度为原数据结构乘logn

对形态不变的树若信息符合区间减法则可以用dfs序维护子树信息,或用树上差分维护路径信息,复杂度同原数据结构

link-cut tree可以支持树形态的简单修改操作,并可以进行链修改或询问,一般复杂度为均摊O(logn),经过一些修改可以在同样复杂度内维护子树信息

点分治/边分治也可用数据结构维护

嵌套数据结构

在必要时,可以把一种数据结构看做另一种数据结构维护的信息,从而将两个数据结构进行嵌套

例如k维树状数组可看做树状数组套k-1维树状数组,不同的数据结构也可以互相嵌套,例如线段树套平衡树实现查询区间<x的个数

由于具体嵌套方式的不同,复杂度通常是原复杂度相加或相乘,但也有例外

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!