1.容器
容器用于容纳元素集合,并对元素集合进行管理和维护.
传统意义上的管理和维护就是:增,删,改,查.
我们分析每种类型容器时,主要分析其增,删,改,查动作实现,及复杂度.
2.哈希表
2.1.结构
2.1.1.图解
哈希表是容器类型.
其元素组织采用桶+链表的复合结构.
上图是一个容量为8
的哈希表的桶结构.桶结构采用数组的形式,每个位置上元素是一个指向节点的指针.
上述桶结构索引0,2,4,5,6
上分别存储节点指针.索引1,3,7
由于下面尚无元素,分别存储了空指针.
通过节点将落在同一个桶内索引上的各个元素组织成一个单向链表.
上图单独列出了桶结构索引0
位置上由三个节点构成的单向链表.
桶索引0
上是指向链表首个节点指针.
为了可以明确容器内元素所在的桶的索引位置,哈希表为元素引入的一致性约束是:
(1). 元素的键结合哈希函数导出一个值在[0
, 桶的容量)之间的哈希值,此哈希值就是元素所在的桶的索引位置.
(2). 桶的某个索引位置上存在的元素之间通过节点以单向链表组织在一起.
2.1.2.存在一致性约束容器特点
(1). 插入无需提供位置信息.
(2). 不支持直接原地修改.一般分解为移除,添加两个过程.
(3). 由于元素值决定其位置,这类容器一般插入元素时,一般以std::pair<key, value>
形式插入.即元素包含键,值两部分.键用来实现一致性约束.值是此键关联的实际内容.
2.2.1.增
插入过程可描述为:
(1). 计算新元素哈希值.
(2). 为新元素分配节点,将节点插入到单向链表.
哈希表可以实现为支持重复元素插入,不支持重复元素插入.
支持重复元素插入时,先从哈希值对应到的单向链表搜索是否存在重复元素.
若不存在,插入到链表首部即可.
若存在,插入到首个重复元素之前即可.
不支持重复元素插入时,先从哈希值对应到的单向链表搜索是否存在重复元素.
若不存在,插入到链表首部即可.
若存在,释放节点,结束.
2.2.2.删
删除元素可描述为:
(1). 计算元素哈希值
(2). 在哈希值对应的单向链表搜索元素.
若找到,则删除.
若无法找到,无需处理.
允许存储重复元素的哈希表,删除时,
若通过提供元素键值进行删除,一般实现为将搜索到的匹配值全部删除.
若通过提供迭代位置进行删除,一般实现为只将位置上节点内元素删除.
2.2.3.查
查找过程可描述为:
(1). 通过键计算哈希值
(2). 在单向链表中查找匹配
2.2.4.改
对于存在一致性约束的容器,一般不会允许直接修改元素的值.
此类操作一般分解为:删除老元素,添加新元素两个过程来实现.
2.3.时间复杂度
评价容器的依据一个是其占据的线性空间,一个是操作执行的时间复杂度.
哈希表的各个操作时间复杂度为:
假设容器的桶结构容量为n
,容器内元素数量为m
,假设哈希结果较为理想,即哈希值近似均匀落在桶的各个索引位置.
(1). 增:Θ(m/n
)
(2). 删:Θ(m/n
)
(3). 查:Θ(m/n
)
(4). 改:Θ(m/n
)