【问题标题】:What is the complexity of search in sorted std::list?在排序的 std::list 中搜索的复杂性是多少?
【发布时间】:2014-11-28 00:39:57
【问题描述】:

在排序的 std::list 中搜索的复杂性是多少?我知道如果数据结构具有随机访问权限,则排序数据中的搜索复杂度为 O(log n)。但是既然list没有随机访问,那么排序的复杂度是多少呢?

【问题讨论】:

  • @dyp 按值搜索的复杂度
  • 请注意,与搜索复杂性无关,应避免使用(链接)列表,除非您知道它们在特定情况下的性能优于向量/数组(这些情况非常罕见)。 C++ 发明者 Bjarne Stroustrup 关于该主题的有趣谈话:youtube.com/watch?v=YQs6IC-vgmo

标签: c++ search std


【解决方案1】:

这取决于您的搜索方式。给定std::list<T> x 和不在列表中的值v

  • std::find(x.begin(), x.end(), value) 是线性搜索,因此需要x.size() 比较和迭代步骤,并且

  • std::binary_search(x.begin(), x.end()) 使用 O(log(x.size())) 比较执行二进制搜索,但它仍然必须线性递增迭代器以解决每个比较的目标(std::lower_bound 等) .如果列表未按排序顺序,则此调用的行为未定义。

一般来说,迭代器递增对于基于节点的容器来说具有不小的成本,因为它涉及指针追逐并且在内存中是非本地的。但是,您需要考虑值类型的比较操作的成本(可能很高,例如对于非常长、几乎相等的字符串)。此外,您可以通过从专用区域分配节点来解决内存局部性问题。

【讨论】:

  • “这取决于你如何搜索”——不。你甚至在你的回答中解释了为什么在每种情况下它都是线性时间......
  • @leemes:正如我试图在我的回答中解释的那样,“它”有点复杂。
  • 他要求复杂性,答案很简单:O(n)。你解释的是cost,而不是complexity。当然,解释还是很有帮助的。
  • @leemes:复杂性不是魔法。它正在测量某物。有趣的测量可能会有所不同。可以说,OP 没有明确说明这一点。
  • 好吧,我想既然他没有要求特定的东西,我们可以放心地假设他只想要一个取决于大小n 的复杂性,并假设每个子操作都具有恒定的复杂性。一个过于精确的表达式是:T_search = T_advance * n + T_compare * log(n),如果你知道 Ts,你可以更好地计算复杂度。 (也许比较扫描整个列表本身,所以你有 O(n log n))
【解决方案2】:

嗯,它是 O(N)。在 std::list 中搜索总是 O(N),无论是否排序。

已排序的集合很有帮助,因为您可以知道自己是不是太远了,或者还不够。但由于您只能从列表的一端开始,因此无济于事。

【讨论】:

  • 感谢您的回复。这意味着即使对 std::list 进行了排序,二进制搜索也无济于事?
  • 是的。一旦你在列表的中间,你就知道你应该向左还是向右......但是你已经通过链接花费了 O(N) 时间到达那里。
  • list是双链表,每个节点都有两个指针指向pre/next。即使您知道节点在中间,您仍然必须通过每个 next 指针才能到达中间。但是,如果你使用vector,它有随机内存访问,你可以直接跳转到中间节点。
  • @user3852441 好吧,它仍然有帮助,正如 KerrekSB 在他的回答中解释的那样。但这无助于降低复杂性。在排序列表和未排序列表中搜索都是线性时间,但前者比后者快,通常还是很多。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多