如何在stl地图中按升序排列键?

时间:2016-04-30 12:16:03

标签: c++ stl maps

当我在for循环中迭代地图时

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

当数据实际以平衡树的形式存储时,如何获得有序列表。此操作的时间复杂度如何O(n)?

2 个答案:

答案 0 :(得分:1)

好问题。 map确实实现为平衡树(通常实现选择红黑树)。整个树中的所有节点都保持值(即不仅仅是叶节点),并且它们被排序以使得&#34;左边的&#34;来自任何节点的分支仅包含值&#34;小于&#34;节点自身的值,使用&#34; right&#34;包含更大值的分支。

例如:

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

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

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

2)如果有一个去了正确的孩子,那么就按照他们的&#34;左孩子&#34;指针尽可能向下,否则......

3)按照链接返回到父节点/祖父节点等节点,直到找到刚刚从其父节点的左节点开始的节点(此时节点的父节点值)将比你提升的任何节点都要大;请注意比较指针/链接一直很便宜,这比比较一些类型的昂贵的关键值更好< / p>

  • 例如,当你将g提升到h时,你将来自一个左子节点,所以应该停在h;然后在下一次迭代中,你首先要升到f,但是看到你没有来自左子,所以要保持从左边的孩子上升到f-to-m,这将是你的下一个在迭代期间停止
  

此操作的时间复杂度如何O(n)?

假设你在纸上画一棵树并用箭头写下来展示你如何使用上面的逻辑遍历树,你会看到你只有在任何给定的&#34;左边的孩子/父母&# 34;链接后跟一个通过相同链接上升。因此,链接遍历的数量是&lt; 2n,比较次数甚至更小 - 显然是O(n)。

答案 1 :(得分:0)

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

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)。