【问题标题】:Most efficient way to insert an element into sorted array and find its index将元素插入排序数组并找到其索引的最有效方法
【发布时间】:2016-06-08 21:21:51
【问题描述】:

我需要将一个元素插入排序范围,但我还需要知道它的索引(范围内小于该元素的元素数)。我想在 O(logN) 时间内做到这一点。我可以用基本的 C++ 容器做到这一点吗?

我正在考虑使用 std::multimap,通过这个容器,我可以将元素插入到它的位置,复杂度为 O(logN)。但是要获取索引,我需要调用 std::distance,它需要 O(N) 次操作,因为 multimap 迭代器不是随机访问。

另一种方法是使用排序 std::vectorstd::binary_search 算法。在这种情况下,搜索需要 O(logN),但插入需要 O(N) 操作,因为插入到向量中间是线性操作。

那么,是否有 std/boost 容器可以用来达到结果,或者我需要为此实现自己的结构?谢谢!

【问题讨论】:

  • 我没有跟上 Boost MultiIndex 的复杂性保证,但你可以看看
  • 我猜在跟踪每个(内部)节点表示的元素数量时,可以使用自定义树/跳过列表实现。但是您是否知道,一旦您插入另一个项目,这样的索引就会失效?
  • 我们所说的索引范围有多大?如果它不是那么大(几百万),您可以使用非常容易编码的 Fenwick 树。否则,您可以编写平衡二叉树并记住每个子树中的节点数。 AFAIK 标准容器在这里没有太大帮助。想知道,是否有什么东西在提升。

标签: c++ algorithm boost binary-search-tree binary-search


【解决方案1】:

你可以使用Boost.MultiIndexranked indices

Live Coliru Demo

#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ranked_index.hpp>
#include <boost/multi_index/identity.hpp>

using namespace boost::multi_index;
using ranked_int_set=multi_index_container<
  int,
  indexed_by<
    ranked_unique<identity<int>>
  >
>;

#include <iostream>

int main()
{
  ranked_int_set s={0,2,4,6,8,10,12,14,16};

  auto it=s.insert(9).first;
  std::cout<<"9 was inserted at position #"<<s.rank(it)<<"\n";
  std::cout<<"14 is located at position #"<<s.find_rank(14)<<"\n";
}

输出

9 被插入到位置 #5 14 位于#8 位置

【讨论】:

    【解决方案2】:

    没有。我找了。

    有一种方法可以实现这一点。从二叉树或跳过列表开始,并保持子树/跳过的大小(一些额外的开销 - 当插入项目时,您必须回溯到父级/跳过和增量,删除类似)。

    那么就可以在lg n时间获取索引,在lg n时间随机访问(通过索引或偏移量),同时保持排序。

    我试图找到一个预先写好的容器来做这件事没有结果,而且这个项目被罐头了,所以我没有时间去写它。

    可以使用完整的数据库,对已排序的列进行索引,并且您可能能够以相当快的速度获得该数字。

    如果简单的线性排序向量不合理(中间插入成本高),您可能还是要考虑使用数据库。

    作为一个看起来很有希望但失败的容器示例,Boost 的 MultiIndex 容器允许您以多种方式索引容器,但顺序索引和有序索引是独立的。因此,您可以知道您插入项目的顺序,以及它在排序之前/之后的位置,而不是它在排序中的索引。

    【讨论】:

    • 从 Boost 1.59 开始,Boost.MultiIndex 提供了ranked indices,正好符合这里的要求。
    • @joaq 啊哈! 2015 年 8 月,也就是我最后一次寻找之后。
    猜你喜欢
    • 2014-06-22
    • 1970-01-01
    • 2019-08-09
    • 1970-01-01
    • 2017-12-14
    • 2014-10-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多