2012-08-27 46 views
3

我有std::multiset如果我從std::multiset::begin()迭代到std::multiset::end()我會得到排序的元素。我如何在這個std::multiset其他獲得中間元素比迭代從std::multiset::begin()std::multiset::begin() + size()/2std :: multiset並找到中間元素

+0

沒有其他辦法,除非事先知道中間元素是什麼,或者您使用不同的數據結構。 – john

+1

這是可能的,但非封裝黑客的便攜式解決方案。例如。 gcc std :: multiset <>使用_Rb_tree,其中_M_begin()僅指向集合的中間。但是_Rb_tree的實現是私有的 - 所以你必須用reinterpret_cast <>或者其他的方法破解這個封裝,而這個_Rb_tree的實現細節就是gcc現在使用的 - 我們不能確定它即使在不同版本的gcc中也是可移植的。 – PiotrNycz

回答

4

這裏是一個解決方案,使中位值的std :: multiset的:

template<class T> 
double GetMedian(const std::multiset<T>& data) 
{ 
    if (data.empty()) 
     return 0; 

    const size_t n = data.size(); 
    double median = 0; 

    auto iter = data.cbegin(); 
    std::advance(iter, n/2); 

    // Middle or average of two middle values 
    if (n % 2 == 0) 
    { 
     const auto iter2 = iter--; 
     median = double(*iter + *iter2)/2; // data[n/2 - 1] AND data[n/2] 
    } 
    else 
    { 
     median = *iter; 
    } 

    return median; 
} 

如果你需要值絕對偏差( mdev)例如:

template<class T> 
double GetMedianAbsoluteDeviation(const std::multiset<T>& data) 
{ 
    const double fMedian = GetMedian(data); 
    std::multiset<double> diff; 
    for (const auto& x : data) 
    { 
     diff.insert(std::abs(fMedian - x)); 
    } 
    return GetMedian(diff); 
} 
+0

謝謝!我更新了評論的文字部分。代碼不變。 – Sergey

相關問題