在stl映射中,关键帧是如何按升序排列的

How are keys arranged in ascending order in stl maps?

本文关键字:何按 升序 排列 关键帧 stl 映射      更新时间:2023-10-16

当我在for循环中迭代映射时

for(auto it : my_map )
cout << it.first << "n" ;

当数据实际上以平衡树的形式存储时,我如何获得有序列表。这个运算的时间复杂度O(n)是多少?

好问题。map实际上被实现为平衡树(通常实现选择红黑树)。整个树中的所有节点都包含值(即,不仅仅是叶节点),并且对它们进行排序,使得任何节点的"左"分支只包含"小于"节点自身值的值,而"右"分支包含更大的值。

例如:

           m
         /   
        f     q
       /    / 
      c   h o   t
         /
        g

要遍历树,首先从C开始,它必须由映射对象本身中的指针跟踪,否则开始就不是O(1)。然后,从任何给定的节点开始,迭代只需执行以下3个选项中的第一个即可:

1) 如果你已经在最右边的节点,地图对象也必须跟踪,停止否则

2) 如果有一个转到右子级,则尽可能向下跟随其"左子级"指针,否则

3) 按照链接返回父节点/父节点等,直到你发现你刚刚从中提升的节点是其父节点的左节点(此时父节点的节点值将大于你从中提升到的任何节点;注意,比较指针/链接总是很便宜,所以这比比较键值要好,因为对某些类型来说,键值可能很昂贵)

  • 例如,当你将g提升到h时,你将来自左子节点,因此应该在h停止;然后在下一次迭代中,你将首先上升到f,但看到你不是来自左子,所以继续上升f到m,这是来自左子的,所以这将是迭代过程中的下一站

这个运算的时间复杂度O(n)是多少?

假设你在纸上画一棵树,并写下箭头,以显示你是如何使用上面的逻辑遍历这棵树的,你会看到你只有一次沿着任何给定的"左子女/父母"链接下降,然后通过同一链接上升。因此,链路遍历的数量是<2n,并且比较的数量甚至更小——所以很明显O(n)。

如果我正确理解您的问题,您需要按顺序获得映射键的列表。我认为以下方法可行:

std::vector<map_type::key_type> keys;
std::transform(my_map.begin(), my_map.end(), std::back_inserter(keys),
               [](map_type::value_type const& v){return v.first;});

它将在O(n)中运行,因为它直接在链接的集合上迭代。按键查找元素是对数的,但迭代是O(n)。