stl 映射中的键如何按升序排列?

How are keys arranged in ascending order in stl maps?

当我在 for 循环中遍历地图时

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

当数据实际以平衡树的形式存储时,我如何获得有序列表。此操作的时间复杂度如何 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)。

好问题。 map 确实实现为平衡树(通常实现选择 red-black 树)。整个树中的所有节点都保存值(即不仅仅是叶节点),并且它们被排序使得来自任何节点的 "left" 分支仅包含值 "less than" 节点自己的值, "right" 包含更大值的分支。

例如:

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

要遍历树,您最初从 C 开始,必须由地图 object 本身中的指针跟踪,否则开始不会是 O(1)。然后从任何给定节点,迭代只是执行以下 3 个适用选项中的第一个:

1) 如果您已经在 right-most 节点,地图 object 也必须跟踪该节点,请停止; 否则...

2) 如果有一个向右走child,那么跟着它的"left child"指针尽量往下走,否则...

3) 跟随 links 回到 parent / grand-parent 等节点,直到你发现你刚刚上升的节点是它的左节点 parent(此时 parent 的节点值将大于您从中提升的任何节点;请注意,比较 pointers/links 始终便宜,因此比比较键值更好这对于某些类型来说可能很昂贵)

  • 例如,当你从g上升到h时,你将来自left-child节点,所以应该停在h;然后在下一次迭代中,您将首先上升到 f,但看到您不是来自 left-child,所以继续上升 f-to-m,它是从左侧 child,所以这将是迭代期间的下一站

Also how is time complexity of this operation O(n) ?

假设你在纸上画了一棵树,并用箭头写出你是如何使用上面的逻辑遍历这棵树的,你会发现在任何给定的 "left child / parent" [=53= 之后你只有一次下降] 然后通过相同的 link 进行一次攀登。因此,link遍历的次数<2n,比较的次数就更少了——显然O(n)。