00001
00002
00003
00004
00005
00006
00007
00008
00009 #ifndef __libutilxx__sella__algo__WRR_H__
00010 #define __libutilxx__sella__algo__WRR_H__
00011
00012 #include "../../common.h"
00013
00014 #include <stdio.h>
00015 #include <string>
00016 #include <map>
00017
00018 namespace sella {
00019 namespace algo {
00020 template <class T> class WRR;
00021
00022 template <class T> class WRRNode {
00023 friend class WRR<T>;
00024
00025 public:
00026 WRRNode(const T & data, double weight = 1.0) throw ();
00027
00028 private:
00029 double weight;
00030
00031 double points;
00032 double rate;
00033
00034 T data;
00035 };
00036
00037 template <class T> class WRR {
00038 public:
00039 WRR() throw ();
00040
00041 void insert(const std::string & identifier, const T & node, double weight = 1.0) throw ();
00042 void remove(const std::string & identifier) throw ();
00043 void update(const std::string & identifier, double weight = 1.0) throw ();
00044
00045 T & next() throw ();
00046
00047 private:
00048 double total;
00049
00050 typename std::map<std::string, WRRNode<T> > node;
00051 typename std::map<std::string, WRRNode<T> >::iterator iter;
00052 };
00053 }
00054 }
00055
00056 template <class T> sella::algo::WRR<T>::WRR() throw () :
00057 total(0.0),
00058
00059 node(),
00060 iter(node.end())
00061 { }
00062
00063 template <class T> sella::algo::WRRNode<T>::WRRNode(const T & data, double weight) throw () :
00064 weight(weight),
00065
00066 points(0.0),
00067 rate(0.0),
00068
00069 data(data)
00070 { }
00071
00072 template <class T> void sella::algo::WRR<T>::insert(const std::string & identifier, const T & node, double weight) throw () {
00073 this->node.insert(std::make_pair(identifier, WRRNode<T>(node, weight)));
00074 this->total += weight;
00075
00076 for (auto iter = this->node.begin(); iter != this->node.end(); ++iter) {
00077 iter->second.rate = iter->second.weight / this->total;
00078 }
00079 }
00080
00081 template <class T> void sella::algo::WRR<T>::remove(const std::string & identifier) throw () {
00082 auto iter = this->node.find(identifier);
00083
00084 if (iter != this->node.end()) {
00085 this->total -= iter->second.weight;
00086
00087 this->node.erase(iter);
00088 }
00089
00090 for (iter = this->node.begin(); iter != this->node.end(); ++iter) {
00091 iter->second.rate = iter->second.weight / this->total;
00092 }
00093 }
00094
00095 template <class T> void sella::algo::WRR<T>::update(const std::string & identifier, double weight) throw () {
00096 auto iter = this->node.find(identifier);
00097
00098 if (iter != this->node.end()) {
00099 iter->weight = weight;
00100
00101 this->total -= iter->second.weight;
00102 this->total += weight;
00103 }
00104
00105 for (iter = this->node.begin(); iter != this->node.end(); ++iter) {
00106 iter->second.rate = iter->second.weight / this->total;
00107 }
00108 }
00109
00110 template <class T> T & sella::algo::WRR<T>::next() throw () {
00111 while (true) {
00112 while (this->iter != this->node.end()) {
00113 auto item = this->iter;
00114
00115 ++(this->iter);
00116
00117 item->second.points += item->second.rate;
00118
00119 if (item->second.points >= 1.0) {
00120 item->second.points -= 1.0;
00121
00122 return item->second.data;
00123 }
00124 }
00125 this->iter = this->node.begin();
00126 }
00127 }
00128
00129 #endif
00130
00131
00132
00133