RunningMedian.h
1 //-*-C++-*-
2 /***************************************************************************
3  *
4  * Copyright (C) 2012 by Willem van Straten
5  * Licensed under the Academic Free License version 2.1
6  *
7  ***************************************************************************/
8 
9 /* Util/genutil/RunningMedian.h */
10 
11 #ifndef __RunningMedian_h
12 #define __RunningMedian_h
13 
14 #include <set> // defines multiset
15 #include <functional> // defines less<>
16 
17 //#define _DEBUG
18 //#include <iostream>
19 
21 
38 template< typename T, typename Compare = std::less<T> >
40 {
41  mutable std::multiset<T,Compare> lowerHalf, upperHalf;
42  Compare lt;
43  unsigned nth;
44 
45 public:
46 
47  RunningMedian (unsigned n=0) { nth = n; }
48  void set_nth (unsigned n) { nth = n; }
49  unsigned get_nth () const { return nth; }
50 
52  void clear () { lowerHalf.clear(); upperHalf.clear(); }
53 
55  void insert (const T& element)
56  {
57 #ifdef _DEBUG
58  std::cerr << "insert sizes lt=" << lowerHalf.size()
59  << " gt=" << upperHalf.size()
60  << " element=" << element << " low=" << *upperHalf.begin()
61  << std::endl;
62 #endif
63 
64  if (upperHalf.size() && lt( element, *upperHalf.begin() ))
65  lowerHalf.insert( element );
66  else
67  upperHalf.insert( element );
68 
69 #ifdef _DEBUG
70  std::cerr << "insert. sizes lt=" << lowerHalf.size()
71  << " gt=" << upperHalf.size() << std::endl;
72 #endif
73  }
74 
76  void erase (const T& element)
77  {
78 #ifdef _DEBUG
79  std::cerr << "erase sizes lt=" << lowerHalf.size()
80  << " gt=" << upperHalf.size()
81  << " element=" << element << " low=" << *upperHalf.begin()
82  << std::endl;
83 #endif
84 
85  if (lt(element, *upperHalf.begin()))
86  lowerHalf.erase( lowerHalf.find( element ) );
87  else
88  upperHalf.erase( upperHalf.find( element ) );
89 
90 #ifdef _DEBUG
91  std::cerr << "erase. sizes lt=" << lowerHalf.size()
92  << " gt=" << upperHalf.size() << std::endl;
93 #endif
94  }
95 
97  const T& get_median () const
98  {
99 #ifdef _DEBUG
100  std::cerr << "median nth=" << nth << " sizes lt=" << lowerHalf.size()
101  << " gt=" << upperHalf.size() << " low=" << *upperHalf.begin()
102  << std::endl;
103 #endif
104 
105  while (upperHalf.size() > nth+1)
106  lowerHalf.insert( popFirstElement( upperHalf ));
107 
108  while (lowerHalf.size() > nth)
109  upperHalf.insert( popLastElement( lowerHalf ));
110 
111  return *upperHalf.begin();
112  }
113 
114 protected:
115 
116  /* helper functions */
117 
118  static T popFirstElement (std::multiset<T,Compare>& S)
119  {
120  T result = *(S.begin());
121  S.erase( S.begin() );
122  return result;
123  }
124 
125  static T popLastElement (std::multiset<T,Compare>& S)
126  {
127  typename std::multiset<T>::iterator it = S.end();
128  it--;
129  T result = *it;
130  S.erase( it );
131  return result;
132  }
133 
134 };
135 
136 #endif
137 
For use in the efficient computation of a running median.
Definition: RunningMedian.h:39
const T & get_median() const
Get the current median value.
Definition: RunningMedian.h:102
void insert(const T &element)
Insert an element.
Definition: RunningMedian.h:60
void erase(const T &element)
Erase an element.
Definition: RunningMedian.h:81
void clear()
Erases all of the elements.
Definition: RunningMedian.h:57

Generated using doxygen 1.8.17