00001
#ifndef TOPNMULTIMAP_H
00002
#define TOPNMULTIMAP_H
00003
00004
#include <exception>
00005
#include <map>
00006
#include <algorithm>
00007
#include <iterator>
00008
#include <Exceptions.h>
00009
#include <maputil.h>
00010
00011
using namespace std;
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
template<
typename TKey,
typename TValue>
00031 class TopNMultimap
00032 {
00033
public:
00034
00035
TopNMultimap(
unsigned int n)
00036
throw (std::exception);
00037
00038
00039
00040
00041
00042
00043
00044
void insert(
const pair<TKey, TValue> & p)
00045
throw (std::exception);
00046
00047
00048
00049
00050
void erase(
const TKey & p)
00051
throw (std::exception);
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
bool findByKey(
const TKey & k, TValue & d,
bool & inTop)
const
00062
throw (std::exception);
00063
00064
00065
00066
00067
const multimap<TValue, TKey> &
getTopMultimap()
const
00068
throw (std::exception);
00069
00070
00071
00072
00073
00074
const multimap<TValue, TKey> &
getBottomMultimap()
const
00075
throw (std::exception);
00076
00077
private:
00078
unsigned int _n;
00079
00080
struct IndexContent
00081 {
00082 IndexContent(
const TValue & v,
char whichPool)
00083 : _v(v),
00084 _whichPool(whichPool)
00085 {}
00086
00087
00088 TValue _v;
00089
00090
00091
00092
char _whichPool;
00093 };
00094
00095
00096
00097
00098 map<TKey, IndexContent> _index;
00099
00100
00101
00102
00103 multimap<TValue, TKey> _topObjects;
00104 multimap<TValue, TKey> _bottomObjects;
00105
00106
00107
00108
00109
00110
char ensureKeyDeleted(
const TKey & k)
00111
throw (std::exception);
00112
00113
00114
00115
00116
00117
void deleteKeyFromPool(
const TKey & k,
char whichPool)
00118
throw (std::exception);
00119
00120
00121
00122
00123
00124
void insertKeyIntoPool(
const TKey & k,
const TValue & v,
char whichPool)
00125
throw (std::exception);
00126
00127
00128
00129
00130
00131
00132
00133
void migrateKey(
const TKey & k,
char oldPool,
char newPool)
00134
throw (std::exception);
00135 };
00136
00137
00138
00139
template<
typename TKey,
typename TValue>
00140 TopNMultimap<TKey, TValue>::TopNMultimap(
unsigned int n)
00141
throw (std::exception)
00142 {
00143 _n = n;
00144 }
00145
00146
00147
00148
template<
typename TKey,
typename TValue>
00149 void TopNMultimap<TKey, TValue>::insert(
const pair<TKey, TValue> & p)
00150
throw (std::exception)
00151 {
00152
const TKey & keyToInsert = p.first;
00153
const TValue & valueToInsert = p.second;
00154
00155
char oldKeyLocation = ensureKeyDeleted(keyToInsert);
00156
00157 size_t topSize = _topObjects.size();
00158
00159
if (topSize < _n)
00160 {
00161
00162
00163
00164 insertKeyIntoPool(keyToInsert, valueToInsert,
't');
00165
return;
00166 }
00167
00168
if (oldKeyLocation ==
't')
00169 {
00170
00171
00172
00173
00174
typename multimap<TValue, TKey>::reverse_iterator bottomPos =
00175 _bottomObjects.rbegin();
00176
00177
00178
if ((valueToInsert) >= (bottomPos->first))
00179 {
00180 insertKeyIntoPool(keyToInsert, valueToInsert,
't');
00181
return;
00182 }
00183
else
00184 {
00185 migrateKey(bottomPos->second,
'b',
't');
00186 insertKeyIntoPool(keyToInsert, valueToInsert,
'b');
00187
return;
00188 }
00189 }
00190
00191
00192
00193
00194
typename multimap<TValue, TKey>::iterator topPos = _topObjects.begin();
00195
00196
00197
if (valueToInsert > topPos->first)
00198 {
00199 migrateKey(topPos->second,
't',
'b');
00200 insertKeyIntoPool(keyToInsert, valueToInsert,
't');
00201
return;
00202 }
00203
else
00204 {
00205 insertKeyIntoPool(keyToInsert, valueToInsert,
'b');
00206
return;
00207 }
00208 }
00209
00210
00211
00212
template<
typename TKey,
typename TValue>
00213 void TopNMultimap<TKey, TValue>::erase(
const TKey & p)
00214
throw (std::exception)
00215 {
00216
char oldKeyLocation = ensureKeyDeleted(p);
00217
00218
if ((oldKeyLocation !=
't') || (_bottomObjects.size() == 0))
00219 {
00220
return;
00221 }
00222
00223
00224
00225
typename multimap<TValue, TKey>::iterator pos = _bottomObjects.end();
00226 --pos;
00227 migrateKey(pos->second,
'b',
't');
00228 }
00229
00230
00231
00232
template<
typename TKey,
typename TValue>
00233 bool TopNMultimap<TKey, TValue>::findByKey(
const TKey & k,
00234 TValue & d,
00235
bool & inTop)
const
00236
throw (std::exception)
00237 {
00238
typename map<TKey, IndexContent>::const_iterator posIndex = _index.find(k);
00239
00240
if (posIndex == _index.end())
00241 {
00242
return false;
00243 }
00244
00245 d = posIndex->second._v;
00246 inTop = (posIndex->second._whichPool ==
't');
00247
return true;
00248 }
00249
00250
00251
00252
template<
typename TKey,
typename TValue>
00253 const multimap<TValue, TKey> &
TopNMultimap<TKey, TValue>::getTopMultimap() const
00254 throw (std::exception)
00255 {
00256
return _topObjects;
00257 }
00258
00259
00260
00261
template<
typename TKey,
typename TValue>
00262 const multimap<TValue, TKey> &
TopNMultimap<TKey, TValue>::getBottomMultimap() const
00263 throw (std::exception)
00264 {
00265
return _bottomObjects;
00266 }
00267
00268
00269
00270
template<
typename TKey,
typename TValue>
00271
char TopNMultimap<TKey, TValue>::ensureKeyDeleted(
const TKey & k)
00272
throw (std::exception)
00273 {
00274
typename map<TKey, IndexContent>::iterator posIndex = _index.find(k);
00275
00276
if (posIndex == _index.end())
00277 {
00278
return 'a';
00279 }
00280
00281
char whichPool = posIndex->second._whichPool;
00282 deleteKeyFromPool(k, whichPool);
00283
return whichPool;
00284 }
00285
00286
00287
00288
template<
typename TKey,
typename TValue>
00289
void TopNMultimap<TKey, TValue>::deleteKeyFromPool(
const TKey & k,
char whichPool)
00290
throw (std::exception)
00291 {
00292
00293
00294
typename map<TKey, IndexContent>::iterator posIndex = _index.find(k);
00295
if (posIndex == _index.end())
00296 {
00297
Throw(
AuroraException,
"The specified key wasn't found in _index");
00298 }
00299
00300
const TValue & v = posIndex->second._v;
00301
00302
00303
00304
00305
00306
00307
int numDeleted = 777;
00308
00309
if (whichPool ==
't')
00310 {
00311 numDeleted =
multimapEraseExact(_topObjects, make_pair(v, k));
00312 }
00313
else if (whichPool ==
'b')
00314 {
00315 numDeleted =
multimapEraseExact(_bottomObjects, make_pair(v, k));
00316 }
00317
else
00318 {
00319
Throw(
AuroraException,
"Invalid value supplied for 'whichPool'");
00320 }
00321
00322
if (numDeleted != 1)
00323 {
00324
Throw(
AuroraException,
"An invalid number of entries was deleted.");
00325 }
00326
00327 _index.erase(posIndex);
00328 }
00329
00330
00331
00332
template<
typename TKey,
typename TValue>
00333
void TopNMultimap<TKey, TValue>::insertKeyIntoPool(
const TKey & k,
const TValue & v,
char whichPool)
00334
throw (std::exception)
00335 {
00336
00337
00338
00339
00340
00341
if (whichPool ==
't')
00342 {
00343 _index.insert(make_pair(k, IndexContent(v,
't')));
00344 _topObjects.insert(make_pair(v, k));
00345 }
00346
else if (whichPool =
'b')
00347 {
00348 _index.insert(make_pair(k, IndexContent(v,
'b')));
00349 _bottomObjects.insert(make_pair(v, k));
00350 }
00351
else
00352 {
00353
Throw(
AuroraException,
"Invalid value supplied for 'whichPool'");
00354 }
00355 }
00356
00357
00358
00359
template<
typename TKey,
typename TValue>
00360
void TopNMultimap<TKey, TValue>::migrateKey(
const TKey & k,
00361
char oldPool,
00362
char newPool)
00363
throw (std::exception)
00364 {
00365
00366
typename map<TKey, IndexContent>::iterator posIndex = _index.find(k);
00367
if (posIndex == _index.end())
00368 {
00369
Throw(
AuroraException,
"The specified key wasn't found in _index");
00370 }
00371
00372
const TValue & v = posIndex->second._v;
00373
00374
00375 pair<TValue, TKey> mmPair(v, k);
00376
00377
if ((oldPool ==
'b') && (newPool =
't'))
00378 {
00379
multimapEraseExact(_bottomObjects, mmPair);
00380 _topObjects.insert(mmPair);
00381 }
00382
else if ((oldPool ==
't') && (newPool =
'b'))
00383 {
00384
multimapEraseExact(_topObjects, mmPair);
00385 _bottomObjects.insert(mmPair);
00386 }
00387
else
00388 {
00389
Throw(
AuroraException,
"Invalid pair of values supplied "
00390
"for 'oldPool' and 'newPool'");
00391 }
00392
00393
00394 posIndex->second._whichPool = newPool;
00395 }
00396
00397
#endif
00398
00399