C++使用参考计算中位数

C++ calculate median with reference

本文关键字:计算 中位数 参考 C++      更新时间:2023-10-16

我尝试计算一个名为 median 的向量的中位数:

std::nth_element(median.begin(), median.begin() + median.size() / 2, median.end());     
medianVal = median[median.size() / 2];  
cout << "The median is " << medianVal << endl;

这工作正常。但是我需要获取中值在其原始向量中的位置。我怎样才能非常快速地做到这一点?

我假设您不想重新排序原始容器。 如果错了,有更简单的方法。

nth_element需要一个比较器。

因此,首先在原始容器中创建一个迭代器的向量,然后编写一个比较器,该比较器需要 2 个迭代器,尊重它们,amd 比较结果。

template<class C>
auto median(C const& c){
  using std::begin; using std::end;
  auto start = begin(c);
  auto finish = end(c);
  using iterator = decltype(start);
  std::vector<iterator> working;
  for(auto it = start; it != finish; ++it)
    working.push_back(it);
  if (working.empty())
      return start;
  std::nth_element(
      begin(working), begin(working) + working.size() / 2, end(working),
      [](iterator lhs, iterator rhs){
          return *lhs < *rhs;
      }
  );
  return *(begin(working) + working.size() / 2);
}

这确实依赖于一些 C++14(自动返回类型推导),但每个主要编译器(可能除了 icc?)现在都支持它。

它足够灵活,甚至可以在 C 样式数组上运行,我认为它甚至可以与哨兵一起使用。

演示

根据文档 (http://en.cppreference.com/w/cpp/algorithm/nth_element),您使用的函数实际上会部分地对数组进行重新排序。

您需要保留原件的副本并逐步浏览它以找到与中位数匹配的元素。

完成它的另一种方法是有一个元组向量,其中索引简单地存储为元组的第二个成员。当然,您仍然会在某个时候逐步通过矢量。

如果不知道问题的确切性质或所涉及的数据系列中的元素数量,就很难知道"非常快地执行此操作"是什么意思,但是您可能想看看 SO 站点中描述的"堆中位数"又名"滚动中位数"又名"流中位数"算法。

使用此方法,您可以存储当前候选中值的索引,而无需再次迭代原始数据数组以查找中位数的索引。您也不需要修改原始容器的顺序。