从概念上理解容器上的位置访问操作

Posted

技术标签:

【中文标题】从概念上理解容器上的位置访问操作【英文标题】:Conceptually understanding positional access operations on containers 【发布时间】:2019-06-13 23:48:18 【问题描述】:

位置访问操作在容器上的定义可能看起来像std::vector,@987654322,对我来说似乎很简单@、std::liststd::forward_list。也就是说,访问集合中的第kth元素包括获取存储在位置kth的元素在集合中X

例如,表达式vec[k-1] 访问std::vector 中的kth,而*std::next(lst.begin(), k-1) 对应于它的std::list 对应项。

然而,当谈到 关联容器std::setstd::unordered_set 时,我不太清楚谈论 位置访问操作 是否真的有意义,因为我没有找到一种直接的方法来确定此类容器中任意位置 kth 的位置。

但是,我们仍然可以像上面显示的 std::list 示例一样继续,即,将迭代器带到关联容器的“第一个”元素(例如,成员函数 begin() 返回的迭代器)和然后将迭代器向前移动 k-1 次(例如,通过std::next())。

我观察到容器 std::vectorstd::dequestd::liststd::forward_list 都是使用 linear 数据结构实现的,而 std::set 通常实现为二叉树,不是。所以,这个问题可能与容器实现的底层数据结构的线性有关。

有没有什么方法可以清楚地定义关联容器的位置访问操作的语义?或者这样的访问操作对他们不适用吗?


不要混淆 searchaccess 操作。在搜索操作中,您正在寻找集合中具有给定键的元素。


X 这与执行此操作所需的运行时间无关(例如,std::list 的线性时间而不是std::vector 的恒定时间)或是否没有专用的成员函数(例如,std::list 中缺少下标运算符)来实现这一点。

【问题讨论】:

【参考方案1】:

您提到的容器类别之间的最大区别在于第一个是 sequence 容器,其中容器的用户明确确定放置元素的位置,而后者是 关联容器,其中生成的顺序由元素的某些属性隐式确定,以便可以通过键 (std::map/std::unordered_map)/值 (std::set/std::unordered_set) 有效地访问它们.

这并不意味着在此类容器中通过“位置”进行访问是没有用的 - 因为std::set 保持其元素排序,std::set 中的第 kth 项是 kth 集合中的最小元素(虽然我确实想不出按位置访问std::unordered_set 的任何目的 - 散列通常不会产生任何特别有用的排序1)。

除了这个概念上的区别之外,我认为访问std::list 的第 kth 元素和在 std::set 上执行相同操作之间没有任何大的操作差异 - 在这两种情况下,操作不是容器“本机”支持的(例如,容器不支持 O(1) 随机访问),并且您必须一次遍历一个元素。即使在底层,像std::setstd::map 通常使用的二叉树也与跟踪链表中的链接(例如std::list)没有太大区别。


    如果std::hash 是一个加密散列,它“白化”了原始数据,它可能是“访问随机排列的某些元素”,但std::hash 只需要很好地分布在类型范围,例如整数 are often hashed as themselves - 不是一个特别有趣的排列。

【讨论】:

【参考方案2】:

当你指向一个列表时,可以定义第 kth 元素,该元素由指向第 kth-1 的指针旁边的指针指向的元素。 sup> 元素。

您还可以注意到,在数论中,数字也被定义为序列: 1 是 0 旁边的数字,2 是 1 旁边的数字,等等……

因此,可以创建由指向容器元素及其下一个操作的指针形成的结构的同构,以及使用 +1 操作的自然数结构:

p0:=begin()                               O
  |next                                   |increment
p1:=next(begin())   --isomorphic to-->    1:=increment(0)
  |next                                   |increment
p2:=next(next(begin()))                   2:=increment(increment(0))
  .                                       .
  .                                       .

这种同构可以用于任何容器,只要它们提供一个开始指针。所以,为了位置的概念,任何 STL 容器都是等价的。

【讨论】:

非常有趣的答案。因此,只要容器为初始元素提供前向迭代器,就可以创建同构。

以上是关于从概念上理解容器上的位置访问操作的主要内容,如果未能解决你的问题,请参考以下文章

STL deque

std::deque

顺序容器2

zrender初步理解

STL容器用法详解及注解(持续更新)

通过jenkins访问windows上的linux挂载位置