c++ - std::map 可以在迭代器处有效地拆分为两个 std::maps 吗?
问题描述
假设我有一个std::map<int, std::string> myMap
包含数据
1. Red
2. Blue
3. Green
5. Fuchsia
6. Mauve
9. Gamboge
10. Vermillion
以及std::map<int, std::string>::iterator it
指向元素
5. Fuchsia
我想做类似的事情(编造这个)
std::map<int, std::string> myHead = eject(myMap, myMap.begin(), it);
这将导致myMap
包含
5. Fuchsia
6. Mauve
9. Gamboge
10. Vermillion
并myHead
包含
1. Red
2. Blue
3. Green
我可以通过做类似的事情来做到这一点
std::map<int, std::string> myHead;
myHead.insert(myMap.begin(), it);
myMap.erase(myMap.begin(), it);
但这至少在某些情况下似乎不是最理想的,例如,如果我选择一个点,我只是分裂一个子树。(我承认我实际上并没有考虑过这里算法复杂性的实际细节,但是如果我们想象一个值类型复制起来非常昂贵的情况,那么很明显,上述方法通常不是最优的.)
问题:有没有一种方法可以让我std::map
以最佳方式执行此操作,或者我是否必须编写自己的二叉搜索树才能访问内部结构来完成此操作?
解决方案
如果我们说的是渐近复杂性,O(log n)
对于大多数自平衡树类型,您可以及时执行此操作,使用通俗地称为split
和的两个操作join
。有一篇关于此的广泛的Wikipedia 文章。
您无法使用 获得这种复杂性std::map
,您需要滚动自己的或第三方的自平衡树实现。如果您需要经常进行此操作,这是非常值得的。使用标准库可以获得的最佳效果是O(n)
,它可能会慢很多数量级。
你可以O(n)
在 C++11 中这样做:
template<class K, class T, class C, class A>
std::map<K, T, C, A> eject(
std::map<K, T, C, A>& my_map,
std::map<K, T, C, A>::iterator begin,
std::map<K, T, C, A>::iterator end,
) {
std::map<K, T, C, A> result;
while (begin != end) {
auto next = std::next(begin);
// C++11
result.insert(result.end(), std::move(*begin));
my_map.erase(begin);
// C++17 (avoids move and destruct)
// result.insert(result.end(), my_map.extract(begin));
begin = next;
}
return result;
}
推荐阅读
- webrtc - WebRTC中TURN服务器和SFU的区别?
- html - 使用 jquery 选择跨度文本
- xamarin - 无法更新 MvvmCross,错误,AndroidX.SavedState 1.0.0.2' 与 'Xamarin.AndroidX.Activity 1.1.0.4' 不兼容
- javascript - 使用数组过滤方法(Javascript)更改对象序列
- reactjs - 当组件依赖于 React 中的两个 props 时,使用哪种生命周期方法?
- javascript - 在javascript中获取ENUM的整数值
- c# - SpinWait.SpinUntil 在等待 Selnium 元素存在时退出的时间比超时时间长得多
- java - 从蓝牙录制音频时在耳机上播放实时音频
- logging - 使用 splunk 绘制从 json 字符串字段中提取的键计数表
- python - 尝试连接到 MongoDB TypeError 时出现 Scrapy 错误:__init__() 缺少 2 个必需的位置参数:“mongo_uri”和“mongo_db”