std::map::merge 的计算时间复杂度
Computational time complexity of std::map::merge
C++17 引入了一个 std::map::merge
函数,用于将一个 std::map
合并到另一个。
因为 std::map
是一个有序的关联容器,更明确地说是一个 自平衡二叉搜索树 (最常实现为红黑树或 AVL 树) ,我希望 std::map::merge
利用两个 std::map
的元素已经排序的事实,因此不需要为每个元素搜索插入位置,即时间复杂度应该线性摊销 O(N)
.
有趣的是,cppreference saysstd::map::merge
的计算时间复杂度是对数的O(N*log(N))
:
Complexity N*log(size()+N)), where N is source.size()
对吗?
在这种情况下 std::map::merge
似乎等同于 std::map::insert(iterator begin, iterator end)
,使得 std::map::merge
完全多余。
std::map::merge
的时间复杂度的真相是什么?
I would expect that std::map::merge takes advantage of the fact that
the elements of both std::maps are already sorted, so there is no need
to search the place of insertion for every single element [...]
您忽略了要合并的地图可能是不同类型的事实,即它可能使用不同的排序:
template <class C2>
void merge(std::map<Key, T, C2, Allocator>& source);
^--- this is not necessarily the same as for the map you
are merging into
因此实际上必须考虑要合并的地图未排序以获得最坏情况的复杂性。
想象一下这个方法的可能实现:
for (auto const& iter : source)
{
dest. insert( iter);
}
因此您遍历源映射(复杂度 N),并将每个元素插入复杂度为 log(dest.size()+N) 的目标映射中。
正如user463035818的另一个答案已经指出的那样,两个映射的顺序不一定相同,因此您必须分别插入每个元素。
最后,树排序算法的构建方式必须是从根节点向下遍历树,并在向下或再次返回时进行平衡。很难编写一个按顺序遍历树的算法,添加元素 和 平衡树。
C++17 引入了一个 std::map::merge
函数,用于将一个 std::map
合并到另一个。
因为 std::map
是一个有序的关联容器,更明确地说是一个 自平衡二叉搜索树 (最常实现为红黑树或 AVL 树) ,我希望 std::map::merge
利用两个 std::map
的元素已经排序的事实,因此不需要为每个元素搜索插入位置,即时间复杂度应该线性摊销 O(N)
.
有趣的是,cppreference saysstd::map::merge
的计算时间复杂度是对数的O(N*log(N))
:
Complexity N*log(size()+N)), where N is source.size()
对吗?
在这种情况下 std::map::merge
似乎等同于 std::map::insert(iterator begin, iterator end)
,使得 std::map::merge
完全多余。
std::map::merge
的时间复杂度的真相是什么?
I would expect that std::map::merge takes advantage of the fact that the elements of both std::maps are already sorted, so there is no need to search the place of insertion for every single element [...]
您忽略了要合并的地图可能是不同类型的事实,即它可能使用不同的排序:
template <class C2>
void merge(std::map<Key, T, C2, Allocator>& source);
^--- this is not necessarily the same as for the map you
are merging into
因此实际上必须考虑要合并的地图未排序以获得最坏情况的复杂性。
想象一下这个方法的可能实现:
for (auto const& iter : source)
{
dest. insert( iter);
}
因此您遍历源映射(复杂度 N),并将每个元素插入复杂度为 log(dest.size()+N) 的目标映射中。
正如user463035818的另一个答案已经指出的那样,两个映射的顺序不一定相同,因此您必须分别插入每个元素。
最后,树排序算法的构建方式必须是从根节点向下遍历树,并在向下或再次返回时进行平衡。很难编写一个按顺序遍历树的算法,添加元素 和 平衡树。