PIMap via pipair, fix tests

This commit is contained in:
Бычков Анлрей
2022-05-26 18:07:44 +03:00
parent 831adf3fc9
commit e85b11a233
3 changed files with 115 additions and 128 deletions

View File

@@ -30,41 +30,6 @@
#include "pipair.h" #include "pipair.h"
template<class T>
void piQuickSort(T * a, ssize_t N) {
if (N < 1) return;
if (N < 46) {
T tmp;
ssize_t i,j;
for(i=1; i<=N; i++) {
tmp = a[i];
j = i-1;
while(tmp<a[j] && j>=0) {
a[j+1] = a[j];
j = j-1;
}
a[j+1] = tmp;
}
} else {
ssize_t i = 0, j = N;
T & p(a[N >> 1]);
do {
while (a[i] < p) i++;
while (a[j] > p) j--;
if (i <= j) {
if (i != j) {
//piCout << "swap" << i << j << a[i] << a[j];
piSwap<T>(a[i], a[j]);
}
i++; j--;
}
} while (i <= j);
if (j > 0) piQuickSort(a, j);
if (N > i) piQuickSort(a + i, N - i);
}
}
template <typename Key, typename T> template <typename Key, typename T>
class PIMapIterator; class PIMapIterator;
@@ -75,9 +40,9 @@ class PIMap {
template <typename Key1, typename T1> friend PIByteArray & operator <<(PIByteArray & s, const PIMap<Key1, T1> & v); template <typename Key1, typename T1> friend PIByteArray & operator <<(PIByteArray & s, const PIMap<Key1, T1> & v);
template <typename Key1, typename T1> friend class PIMapIterator; template <typename Key1, typename T1> friend class PIMapIterator;
public: public:
PIMap() {;} PIMap() {}
PIMap(const PIMap<Key, T> & other) {*this = other;} PIMap(const PIMap<Key, T> & other) {*this = other;}
PIMap(PIMap<Key, T> && other) : pim_content(std::move(other.pim_content)), pim_index(std::move(other.pim_index)) {} PIMap(PIMap<Key, T> && other) : pim_content(std::move(other.pim_content)) {}
PIMap(std::initializer_list<std::pair<Key, T>> init_list) { PIMap(std::initializer_list<std::pair<Key, T>> init_list) {
for (auto i: init_list) for (auto i: init_list)
insert(std::get<0>(i), std::get<1>(i)); insert(std::get<0>(i), std::get<1>(i));
@@ -88,7 +53,6 @@ public:
if (this == &other) return *this; if (this == &other) return *this;
clear(); clear();
pim_content = other.pim_content; pim_content = other.pim_content;
pim_index = other.pim_index;
return *this; return *this;
} }
@@ -203,12 +167,15 @@ public:
T & operator [](const Key & key) { T & operator [](const Key & key) {
bool f(false); bool f(false);
ssize_t i = _find(key, f); ssize_t i = _find(key, f);
if (f) return pim_content[pim_index[i].index]; if (!f) pim_content.insert(i, PIPair<Key, T>(key, T()));
pim_content.push_back(T()); return pim_content[i].second;
pim_index.insert(i, MapIndex(key, pim_content.size() - 1)); }
return pim_content.back(); const T operator [](const Key & key) const {
bool f(false);
ssize_t i = _find(key, f);
if (f) return pim_content[i].second;
return T();
} }
const T operator [](const Key & key) const {bool f(false); ssize_t i = _find(key, f); if (f) return pim_content[pim_index[i].index]; return T();}
const T at(const Key & key) const {return (*this)[key];} const T at(const Key & key) const {return (*this)[key];}
PIMap<Key, T> & operator <<(const PIMap<Key, T> & other) { PIMap<Key, T> & operator <<(const PIMap<Key, T> & other) {
@@ -219,27 +186,26 @@ public:
#endif #endif
assert(&other != this); assert(&other != this);
if (other.isEmpty()) return *this; if (other.isEmpty()) return *this;
if (other.size() == 1) {insert(other.pim_index[0].key, other.pim_content[0]); return *this;} // if (other.size() == 1) {insert(other.pim_index[0].key, other.pim_content[0]); return *this;}
if (other.size() == 2) {insert(other.pim_index[0].key, other.pim_content[0]); insert(other.pim_index[1].key, other.pim_content[1]); return *this;} // if (other.size() == 2) {insert(other.pim_index[0].key, other.pim_content[0]); insert(other.pim_index[1].key, other.pim_content[1]); return *this;}
for (int i = 0; i < other.pim_index.size_s(); ++i) for (int i = 0; i < other.pim_content.size_s(); ++i)
insert(other.pim_index[i].key, other.pim_content[other.pim_index[i].index]); insert(other.pim_content[i].first, other.pim_content[i].second);
return *this; return *this;
} }
bool operator ==(const PIMap<Key, T> & t) const {return (pim_content == t.pim_content && pim_index == t.pim_index);} bool operator ==(const PIMap<Key, T> & t) const {return (pim_content == t.pim_content);}
bool operator !=(const PIMap<Key, T> & t) const {return (pim_content != t.pim_content || pim_index != t.pim_index);} bool operator !=(const PIMap<Key, T> & t) const {return (pim_content != t.pim_content);}
bool contains(const Key & key) const {bool f(false); _find(key, f); return f;} bool contains(const Key & key) const {bool f(false); _find(key, f); return f;}
PIMap<Key, T> & reserve(size_t new_size) {pim_content.reserve(new_size); pim_index.reserve(new_size); return *this;} PIMap<Key, T> & reserve(size_t new_size) {pim_content.reserve(new_size);return *this;}
PIMap<Key, T> & removeOne(const Key & key) {bool f(false); ssize_t i = _find(key, f); if (f) _remove(i); return *this;} PIMap<Key, T> & removeOne(const Key & key) {bool f(false); ssize_t i = _find(key, f); if (f) _remove(i); return *this;}
PIMap<Key, T> & remove(const Key & key) {return removeOne(key);} PIMap<Key, T> & remove(const Key & key) {return removeOne(key);}
PIMap<Key, T> & erase(const Key & key) {return removeOne(key);} PIMap<Key, T> & erase(const Key & key) {return removeOne(key);}
PIMap<Key, T> & clear() {pim_content.clear(); pim_index.clear(); return *this;} PIMap<Key, T> & clear() {pim_content.clear(); return *this;}
void swap(PIMap<Key, T> & other) { void swap(PIMap<Key, T> & other) {
pim_content.swap(other.pim_content); pim_content.swap(other.pim_content);
pim_index.swap(other.pim_index);
} }
PIMap<Key, T> & insert(const Key & key, const T & value) { PIMap<Key, T> & insert(const Key & key, const T & value) {
@@ -247,10 +213,9 @@ public:
ssize_t i = _find(key, f); ssize_t i = _find(key, f);
//piCout << "insert key=" << key << "found=" << f << "index=" << i << "value=" << value; //piCout << "insert key=" << key << "found=" << f << "index=" << i << "value=" << value;
if (f) { if (f) {
pim_content[pim_index[i].index] = value; pim_content[i].second = value;
} else { } else {
pim_content.push_back(value); pim_content.insert(i, PIPair<Key, T>(key, value));
pim_index.insert(i, MapIndex(key, pim_content.size() - 1));
} }
return *this; return *this;
} }
@@ -259,20 +224,34 @@ public:
ssize_t i = _find(key, f); ssize_t i = _find(key, f);
//piCout << "insert key=" << key << "found=" << f << "index=" << i << "value=" << value; //piCout << "insert key=" << key << "found=" << f << "index=" << i << "value=" << value;
if (f) { if (f) {
pim_content[pim_index[i].index] = std::move(value); pim_content[i].second = std::move(value);
} else { } else {
pim_content.push_back(std::move(value)); // pim_content.push_back(std::move(value));
pim_index.insert(i, MapIndex(key, pim_content.size() - 1)); // pim_index.insert(i, MapIndex(key, pim_content.size() - 1));
pim_content.insert(i, PIPair<Key, T>(key, std::move(value)));
} }
return *this; return *this;
} }
const T value(const Key & key, const T & default_ = T()) const {bool f(false); ssize_t i = _find(key, f); if (!f) return default_; return pim_content[pim_index[i].index];} const T value(const Key & key, const T & default_ = T()) const {
PIVector<T> values() const {return pim_content;} bool f(false);
Key key(const T & value_, const Key & default_ = Key()) const {for (int i = 0; i < pim_index.size_s(); ++i) if (pim_content[pim_index[i].index] == value_) return pim_index[i].key; return default_;} ssize_t i = _find(key, f);
if (!f) return default_;
return pim_content[i].second;
}
PIVector<T> values() const {
PIVector<T> ret;
for (size_t i = 0; i < pim_content.size(); ++i) ret << pim_content[i].second;
return ret;
}
Key key(const T & value_, const Key & default_ = Key()) const {
for (int i = 0; i < pim_content.size_s(); ++i)
if (pim_content[i].second == value_)
return pim_content[i].first;
return default_;
}
PIVector<Key> keys() const { PIVector<Key> keys() const {
PIVector<Key> ret; PIVector<Key> ret;
for (int i = 0; i < pim_index.size_s(); ++i) for (size_t i = 0; i < pim_content.size(); ++i) ret << pim_content[i].first;
ret << pim_index[i].key;
return ret; return ret;
} }
@@ -280,66 +259,53 @@ public:
piCout << "PIMap" << size() << "entries" << PICoutManipulators::NewLine << "content:"; piCout << "PIMap" << size() << "entries" << PICoutManipulators::NewLine << "content:";
for (size_t i = 0; i < pim_content.size(); ++i) for (size_t i = 0; i < pim_content.size(); ++i)
piCout << PICoutManipulators::Tab << i << ":" << pim_content[i]; piCout << PICoutManipulators::Tab << i << ":" << pim_content[i];
piCout << "index:"; // piCout << "index:";
for (size_t i = 0; i < pim_index.size(); ++i) // for (size_t i = 0; i < pim_index.size(); ++i)
piCout << PICoutManipulators::Tab << i << ":" << pim_index[i].key << "->" << pim_index[i].index; // piCout << PICoutManipulators::Tab << i << ":" << pim_index[i].key << "->" << pim_index[i].index;
} }
protected: protected:
struct MapIndex { // struct MapIndex {
MapIndex(Key k = Key(), size_t i = 0): key(k), index(i) {;} // MapIndex(Key k = Key(), size_t i = 0): key(k), index(i) {;}
Key key; // Key key;
size_t index; // size_t index;
bool operator ==(const MapIndex & s) const {return key == s.key;} // bool operator ==(const MapIndex & s) const {return key == s.key;}
bool operator !=(const MapIndex & s) const {return key != s.key;} // bool operator !=(const MapIndex & s) const {return key != s.key;}
bool operator <(const MapIndex & s) const {return key < s.key;} // bool operator <(const MapIndex & s) const {return key < s.key;}
bool operator >(const MapIndex & s) const {return key > s.key;} // bool operator >(const MapIndex & s) const {return key > s.key;}
}; // };
template <typename Key1, typename T1> friend PIByteArray & operator >>(PIByteArray & s, PIDeque<typename PIMap<Key1, T1>::MapIndex> & v); // template <typename Key1, typename T1> friend PIByteArray & operator >>(PIByteArray & s, PIDeque<typename PIMap<Key1, T1>::MapIndex> & v);
template <typename Key1, typename T1> friend PIByteArray & operator <<(PIByteArray & s, const PIDeque<typename PIMap<Key1, T1>::MapIndex> & v); // template <typename Key1, typename T1> friend PIByteArray & operator <<(PIByteArray & s, const PIDeque<typename PIMap<Key1, T1>::MapIndex> & v);
ssize_t binarySearch(ssize_t first, ssize_t last, const Key & key, bool & found) const { ssize_t binarySearch(ssize_t first, ssize_t last, const Key & key, bool & found) const {
ssize_t mid; ssize_t mid;
while (first <= last) { while (first <= last) {
mid = (first + last) / 2; mid = (first + last) / 2;
if (key > pim_index[mid].key) first = mid + 1; if (key > pim_content[mid].first) first = mid + 1;
else if (key < pim_index[mid].key) last = mid - 1; else if (key < pim_content[mid].first) last = mid - 1;
else {found = true; return mid;} else {found = true; return mid;}
} }
found = false; found = false;
return first; return first;
} }
void _sort() {piQuickSort<MapIndex>(pim_index.data(), pim_index.size_s() - 1);}
ssize_t _find(const Key & k, bool & found) const { ssize_t _find(const Key & k, bool & found) const {
if (pim_index.isEmpty()) { if (pim_content.isEmpty()) {
found = false; found = false;
return 0; return 0;
} }
return binarySearch(0, pim_index.size_s() - 1, k, found); return binarySearch(0, pim_content.size_s() - 1, k, found);
} }
void _remove(ssize_t index) { void _remove(ssize_t index) {
//if (index >= pim_index.size()) return; pim_content.remove(index);
size_t ci = pim_index[index].index, bi = pim_index.size() - 1;
pim_index.remove(index);
for (size_t i = 0; i < pim_index.size(); ++i)
if (pim_index[i].index == bi) {
pim_index[i].index = ci;
break;
}
piSwap<T>(pim_content[ci], pim_content.back());
pim_content.resize(pim_index.size());
} }
const value_type _pair(ssize_t index) const { const value_type _pair(ssize_t index) const {
if (index < 0 || index >= pim_index.size_s()) if (index < 0 || index >= pim_content.size_s()) return value_type();
return value_type(); return pim_content[index];
//piCout << "_pair" << index << pim_index[index].index;
return value_type(pim_index[index].key, pim_content[pim_index[index].index]);
} }
Key & _key(ssize_t index) {return pim_index[index].key;} Key & _key(ssize_t index) {return pim_content[index].first;}
T & _value(ssize_t index) {return pim_content[pim_index[index].index];} T & _value(ssize_t index) {return pim_content[index].second;}
PIVector<T> pim_content; PIDeque<PIPair<Key, T>> pim_content;
PIDeque<MapIndex> pim_index;
}; };

View File

@@ -630,9 +630,9 @@ inline PIByteArray & operator >>(PIByteArray & s, PIVector2D<T> & v) {
//! \~russian Оператор сохранения //! \~russian Оператор сохранения
template <typename Key, typename T> template <typename Key, typename T>
inline PIByteArray & operator <<(PIByteArray & s, const PIMap<Key, T> & v) { inline PIByteArray & operator <<(PIByteArray & s, const PIMap<Key, T> & v) {
s << int(v.pim_index.size_s()); // s << int(v.pim_index.size_s());
for (uint i = 0; i < v.size(); ++i) // for (uint i = 0; i < v.size(); ++i)
s << int(v.pim_index[i].index) << v.pim_index[i].key; // s << int(v.pim_index[i].index) << v.pim_index[i].key;
s << v.pim_content; s << v.pim_content;
return s; return s;
} }
@@ -647,17 +647,17 @@ inline PIByteArray & operator >>(PIByteArray & s, PIMap<Key, T> & v) {
printf("error with PIMap<%s, %s>\n", __PIP_TYPENAME__(Key), __PIP_TYPENAME__(T)); printf("error with PIMap<%s, %s>\n", __PIP_TYPENAME__(Key), __PIP_TYPENAME__(T));
assert(s.size_s() >= 4); assert(s.size_s() >= 4);
} }
int sz; s >> sz; v.pim_index.resize(sz); // int sz; s >> sz; v.pim_index.resize(sz);
int ind = 0; // int ind = 0;
for (int i = 0; i < sz; ++i) { // for (int i = 0; i < sz; ++i) {
s >> ind >> v.pim_index[i].key; // s >> ind >> v.pim_index[i].key;
v.pim_index[i].index = ind; // v.pim_index[i].index = ind;
} // }
s >> v.pim_content; s >> v.pim_content;
if (v.pim_content.size_s() != v.pim_index.size_s()) { // if (v.pim_content.size_s() != v.pim_index.size_s()) {
piCout << "Warning: loaded invalid PIMap, clear"; // piCout << "Warning: loaded invalid PIMap, clear";
v.clear(); // v.clear();
} // }
return s; return s;
} }

View File

@@ -9,10 +9,33 @@ int main(int argc, char * argv[]) {
PITimeMeasurer tm; PITimeMeasurer tm;
PIStringList small_sl;
PIStringList big_sl;
// {
// for (int i=0; i<small_cnt; ++i) small_sl << PIString::fromNumber(randomi())+PIString::fromNumber(i);
// for (int i=0; i<big_cnt; ++i) big_sl << PIString::fromNumber(randomi())+PIString::fromNumber(i);
// PIFile f;
// f.open("test.bin", PIIODevice::WriteOnly);
// PIByteArray slba;
// slba << small_sl;
// slba << big_sl;
// f.write(slba);
// f.close();
// return 0;
// }
{
PIFile f;
f.open("test.bin", PIIODevice::ReadOnly);
PIByteArray slba = f.readAll();
slba >> small_sl;
slba >> big_sl;
f.close();
}
piCout << "map<int, int> insert..."; piCout << "map<int, int> insert...";
tm.reset(); tm.reset();
for (int c=0; c<repeat; ++c) { for (int c=0; c<repeat; ++c) {
PIMap<int, int> m1; PIMap<int64_t, int64_t> m1;
for (int i=0; i<small_cnt; ++i) { for (int i=0; i<small_cnt; ++i) {
m1.insert(i, i); m1.insert(i, i);
} }
@@ -21,7 +44,7 @@ int main(int argc, char * argv[]) {
piCout << "map<int, int> insert []..."; piCout << "map<int, int> insert []...";
tm.reset(); tm.reset();
for (int c=0; c<repeat; ++c) { for (int c=0; c<repeat; ++c) {
PIMap<int, int> m1; PIMap<int64_t, int64_t> m1;
for (int i=0; i<small_cnt; ++i) { for (int i=0; i<small_cnt; ++i) {
m1[i] = i; m1[i] = i;
} }
@@ -30,7 +53,7 @@ int main(int argc, char * argv[]) {
piCout << "map<int, int> insert rnd..."; piCout << "map<int, int> insert rnd...";
tm.reset(); tm.reset();
for (int c=0; c<repeat; ++c) { for (int c=0; c<repeat; ++c) {
PIMap<int, int> m1; PIMap<int64_t, int64_t> m1;
for (int i=0; i<small_cnt; ++i) { for (int i=0; i<small_cnt; ++i) {
m1.insert(randomi(), i); m1.insert(randomi(), i);
} }
@@ -39,7 +62,7 @@ int main(int argc, char * argv[]) {
piCout << "map<int, int> insert rnd []..."; piCout << "map<int, int> insert rnd []...";
tm.reset(); tm.reset();
for (int c=0; c<repeat; ++c) { for (int c=0; c<repeat; ++c) {
PIMap<int, int> m1; PIMap<int64_t, int64_t> m1;
for (int i=0; i<small_cnt; ++i) { for (int i=0; i<small_cnt; ++i) {
m1[randomi()] = i; m1[randomi()] = i;
} }
@@ -49,7 +72,7 @@ int main(int argc, char * argv[]) {
piCout << "bigmap<int, int> insert..."; piCout << "bigmap<int, int> insert...";
tm.reset(); tm.reset();
for (int c=0; c<no_repeat; ++c) { for (int c=0; c<no_repeat; ++c) {
PIMap<int, int> m1; PIMap<int64_t, int64_t> m1;
for (int i=0; i<big_cnt; ++i) { for (int i=0; i<big_cnt; ++i) {
m1.insert(i, i); m1.insert(i, i);
} }
@@ -58,7 +81,7 @@ int main(int argc, char * argv[]) {
piCout << "bigmap<int, int> insert []..."; piCout << "bigmap<int, int> insert []...";
tm.reset(); tm.reset();
for (int c=0; c<no_repeat; ++c) { for (int c=0; c<no_repeat; ++c) {
PIMap<int, int> m1; PIMap<int64_t, int64_t> m1;
for (int i=0; i<big_cnt; ++i) { for (int i=0; i<big_cnt; ++i) {
m1[i] = i; m1[i] = i;
} }
@@ -67,7 +90,7 @@ int main(int argc, char * argv[]) {
piCout << "bigmap<int, int> insert rnd..."; piCout << "bigmap<int, int> insert rnd...";
tm.reset(); tm.reset();
for (int c=0; c<no_repeat; ++c) { for (int c=0; c<no_repeat; ++c) {
PIMap<int, int> m1; PIMap<int64_t, int64_t> m1;
for (int i=0; i<big_cnt; ++i) { for (int i=0; i<big_cnt; ++i) {
m1.insert(randomi(), i); m1.insert(randomi(), i);
} }
@@ -76,17 +99,13 @@ int main(int argc, char * argv[]) {
piCout << "bigmap<int, int> insert rnd []..."; piCout << "bigmap<int, int> insert rnd []...";
tm.reset(); tm.reset();
for (int c=0; c<no_repeat; ++c) { for (int c=0; c<no_repeat; ++c) {
PIMap<int, int> m1; PIMap<int64_t, int64_t> m1;
for (int i=0; i<big_cnt; ++i) { for (int i=0; i<big_cnt; ++i) {
m1[randomi()] = i; m1[randomi()] = i;
} }
} }
piCout << "bigmap<int, int> insert rnd []" << tm.elapsed_m(); piCout << "bigmap<int, int> insert rnd []" << tm.elapsed_m();
PIStringList small_sl;
for (int i=0; i<small_cnt; ++i) small_sl << PIString::fromNumber(randomd())+PIString::fromNumber(i);
PIStringList big_sl;
for (int i=0; i<big_cnt; ++i) big_sl << PIString::fromNumber(randomd())+PIString::fromNumber(i);
piCout << "map<PIString, int> insert..."; piCout << "map<PIString, int> insert...";
tm.reset(); tm.reset();
for (int c=0; c<repeat; ++c) { for (int c=0; c<repeat; ++c) {
@@ -154,10 +173,11 @@ int main(int argc, char * argv[]) {
PIByteArray ba; PIByteArray ba;
ba.resize(1024); ba.resize(64*1024);
piCout << "map<int, PIByteArray> insert..."; piCout << "map<int, PIByteArray> insert...";
tm.reset();
PIMap<int, PIByteArray> m3; PIMap<int, PIByteArray> m3;
m3.reserve(big_cnt);
tm.reset();
for (int i=0; i<big_cnt; ++i) m3.insert(i, ba); for (int i=0; i<big_cnt; ++i) m3.insert(i, ba);
piCout << "map<int, PIByteArray> insert" << tm.elapsed_m(); piCout << "map<int, PIByteArray> insert" << tm.elapsed_m();
piCout << "map<int, PIByteArray> interate..."; piCout << "map<int, PIByteArray> interate...";
@@ -171,8 +191,9 @@ int main(int argc, char * argv[]) {
piCout << "map<int, PIByteArray> interate" << tm.elapsed_m(); piCout << "map<int, PIByteArray> interate" << tm.elapsed_m();
piCout << "map<PIString, PIByteArray> insert..."; piCout << "map<PIString, PIByteArray> insert...";
tm.reset();
PIMap<PIString, PIByteArray> m4; PIMap<PIString, PIByteArray> m4;
m4.reserve(big_cnt);
tm.reset();
for (int i=0; i<big_cnt; ++i) { for (int i=0; i<big_cnt; ++i) {
m4.insert(big_sl[i], ba); m4.insert(big_sl[i], ba);
} }