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
37
38template< typename T, typename Compare = std::less<T> >
39class RunningMedian
40{
41 mutable std::multiset<T,Compare> lowerHalf, upperHalf;
42 Compare lt;
43 unsigned nth;
44
45public:
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
114protected:
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
const T & get_median() const
Get the current median value.
Definition RunningMedian.h:97
void insert(const T &element)
Insert an element.
Definition RunningMedian.h:55
void clear()
Erases all of the elements.
Definition RunningMedian.h:52
void erase(const T &element)
Erase an element.
Definition RunningMedian.h:76

Generated using doxygen 1.14.0