mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-21 15:10:19 +00:00
AK: Use AK:quickselect_inline
to compute AK::Statistics::median
Quick select is an algorithm that is able to find the median of a Vector without fully sorting it. This replaces the old very naive implementation for `AK::Statistics::median()` with `AK::quickselect_inline`
This commit is contained in:
parent
becd6d106f
commit
6b9344e86c
Notes:
sideshowbarker
2024-07-17 00:50:01 +09:00
Author: https://github.com/Popaulol Commit: https://github.com/SerenityOS/serenity/commit/6b9344e86c Pull-request: https://github.com/SerenityOS/serenity/pull/16906 Reviewed-by: https://github.com/BenWiederhake
1 changed files with 27 additions and 6 deletions
|
@ -8,7 +8,7 @@
|
|||
|
||||
#include <AK/Concepts.h>
|
||||
#include <AK/Math.h>
|
||||
#include <AK/QuickSort.h>
|
||||
#include <AK/QuickSelect.h>
|
||||
#include <AK/Vector.h>
|
||||
|
||||
namespace AK {
|
||||
|
@ -27,10 +27,24 @@ public:
|
|||
}
|
||||
|
||||
T const sum() const { return m_sum; }
|
||||
float average() const { return (float)sum() / size(); }
|
||||
|
||||
// FIXME: Unclear Wording, average can mean a lot of different things
|
||||
// Median, Arithmetic Mean (which this is), Geometric Mean, Harmonic Mean etc
|
||||
float average() const
|
||||
{
|
||||
// Let's assume the average of an empty dataset is 0
|
||||
if (size() == 0)
|
||||
return 0;
|
||||
|
||||
// TODO: sum might overflow so maybe do multiple partial sums and intermediate divisions here
|
||||
return (float)sum() / size();
|
||||
}
|
||||
|
||||
T const min() const
|
||||
{
|
||||
// Lets Rather fail than read over the end of a collection
|
||||
VERIFY(size() != 0);
|
||||
|
||||
T minimum = m_values[0];
|
||||
for (T number : values()) {
|
||||
if (number < minimum) {
|
||||
|
@ -42,6 +56,9 @@ public:
|
|||
|
||||
T const max() const
|
||||
{
|
||||
// Lets Rather fail than read over the end of a collection
|
||||
VERIFY(size() != 0);
|
||||
|
||||
T maximum = m_values[0];
|
||||
for (T number : values()) {
|
||||
if (number > maximum) {
|
||||
|
@ -51,16 +68,20 @@ public:
|
|||
return maximum;
|
||||
}
|
||||
|
||||
// FIXME: Implement a better algorithm
|
||||
T const median()
|
||||
{
|
||||
quick_sort(m_values);
|
||||
// Let's assume the Median of an empty dataset is 0
|
||||
if (size() == 0)
|
||||
return 0;
|
||||
|
||||
// If the number of values is even, the median is the arithmetic mean of the two middle values
|
||||
if (size() % 2 == 0) {
|
||||
auto index = size() / 2;
|
||||
return (m_values.at(index) + m_values.at(index + 1)) / 2;
|
||||
auto median1 = m_values.at(AK::quickselect_inplace(m_values, index));
|
||||
auto median2 = m_values.at(AK::quickselect_inplace(m_values, index - 1));
|
||||
return (median1 + median2) / 2;
|
||||
}
|
||||
return m_values.at(size() / 2);
|
||||
return m_values.at(AK::quickselect_inplace(m_values, size() / 2));
|
||||
}
|
||||
|
||||
float standard_deviation() const { return sqrt(variance()); }
|
||||
|
|
Loading…
Reference in a new issue