【问题标题】:How to get which integer is in a certain position in a set?如何获取集合中某个位置的整数?
【发布时间】:2014-12-12 22:57:27
【问题描述】:

给定一组整数,如果一个集合的元素以递增的方式排序,我怎么知道哪个整数在某个位置?例如,给定一组整数,如何获得较小的整数或第二个较小的整数等

是否可以在对数时间内做到这一点?我的意思是,我知道有很明显的方法可以按照我的要求做,但是有没有在对数时间内有效的方法?

【问题讨论】:

  • 在有序集合中,您应该能够在恒定时间 O(1) 内做到这一点。最小的整数在 S[0] 处,第二小的整数在 S[1] 处,还是我遗漏了什么?
  • 您可能会惊讶于向量对于整数的速度有多快。像 $v.insert(std::lower_bound(v.begin(), v.end(), new_val), new_val);$ 作为插入函数,然后只需 $v[k]$ 即可找出其中的值地点k。插入确实需要在插入点之后复制所有数据,但找到该点是 log(n) 时间,并且通常复制是一条 CPU 指令,尽管可能是几个周期。尝试一下,对其进行基准测试,看看它是否满足您的需求。

标签: c++ performance stl set binary-search-tree


【解决方案1】:

std::set 的元素以递增的顺序存储

不,您无法在对数时间内找到位置 N 处的项目 - 它需要线性时间。

auto start = your_set.begin();
std::advance(start, N);

理论上它可以通过让树的每个节点在其左侧存储节点的计数(即按顺序在其前面)以对数时间完成,但std::set 没有'不需要或提供(标准化)接口来使用它,即使它存在。

【讨论】:

  • 是否可以使用 std::multiset 在对数时间内完成?
  • 是的,std::multiset 的工作方式相同,只是它可以保存重复值。只要按升序排序,就可以按对数时间查询。但是,在什么情况下您想使用多重集?
  • 基本上,我想在对数时间内找到位置 N 的项目。我不能使用数组,因为在整个程序中,用户将删除和插入项目,然后对元素进行排序效率太低。另外我不想实现自己的AVL-Tree或Red-Black Tree,只是因为我想知道如何以更标准化的方式解决这类问题,利用STL库,以便编写代码不会那么耗时。
  • @Francisco:标准库没有提供非常适合此特定任务的数据结构。正如我在答案中所说,要执行您想要的操作,每个节点都需要在其左侧存储节点的计数(并且您需要在添加/删除节点时更新该计数)。标准库没有任何东西可以做到这一点,所以如果你想要它,你需要自己做。
  • 这是std 中缺少的容器:快速索引排序树。孩子总数或左孩子总数都可以工作。
【解决方案2】:

是的,如果您的元素已排序(“以递增方式排序”),那么有一种方法可以在对数时间内搜索任意整数。使用二叉搜索树。显然,如果你想要尽可能好的时间跨度,你会想要使用自平衡树(例如红黑树、avl 树……)。我相信这方面的 C++ 选项是std::set 的一部分。

但是,我不太确定您所说的“获得较小的整数”是什么意思。如果您的意思是,给定一组整数,找到最小元素,那么您将需要查找堆。堆比树做得更好,因为在堆的情况下,查询最小值将在恒定时间内发生,而插入和删除则在对数时间内发生。我相信这方面的 C++ 选项是std::priority_queue 的一部分。

或者,如果您想以最快的方式搜索整数,您可以使用哈希表,因为它们允许在预期的恒定时间内进行查询,并带有恒定的时间插入。用于此的 C++ 选项是 std::unordered_set

【讨论】:

  • 我的意思是,给定一组整数,是否可以在对数时间内找到位置 N 处的元素?(无需实现我自己的 AVL 树或红黑树)
猜你喜欢
  • 1970-01-01
  • 2021-02-10
  • 2012-03-10
  • 2017-08-08
  • 1970-01-01
  • 2011-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多