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)。
当我在 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)。