297 lines
7.9 KiB
C++
297 lines
7.9 KiB
C++
/*! \file piset.h
|
|
* \brief Set container
|
|
*
|
|
* This file declare PISet
|
|
*/
|
|
/*
|
|
PIP - Platform Independent Primitives
|
|
Set container
|
|
Ivan Pelipenko peri4ko@yandex.ru
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU Lesser General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef PISET_H
|
|
#define PISET_H
|
|
|
|
#include "pimap.h"
|
|
|
|
/*! \brief Set of any type
|
|
* \details This class used to store collection of unique elements
|
|
* of any type. You can only add values to set with \a operator<< or
|
|
* with function \a insert(). You can discover if value already in
|
|
* set with \a operator[] or with function \a find(). These function
|
|
* has logarithmic complexity.
|
|
*/
|
|
template<typename T>
|
|
class PISet: public PIMap<T, uchar> {
|
|
typedef PIMap<T, uchar> _CSet;
|
|
|
|
public:
|
|
//! Contructs an empty set
|
|
PISet() {}
|
|
|
|
//! Contructs set with one element "value"
|
|
explicit PISet(const T & value) { _CSet::insert(value, 0); }
|
|
|
|
//! Contructs set with elements "v0" and "v1"
|
|
PISet(const T & v0, const T & v1) {
|
|
_CSet::insert(v0, 0);
|
|
_CSet::insert(v1, 0);
|
|
}
|
|
|
|
//! Contructs set with elements "v0", "v1" and "v2"
|
|
PISet(const T & v0, const T & v1, const T & v2) {
|
|
_CSet::insert(v0, 0);
|
|
_CSet::insert(v1, 0);
|
|
_CSet::insert(v2, 0);
|
|
}
|
|
|
|
//! Contructs set with elements "v0", "v1", "v2" and "v3"
|
|
PISet(const T & v0, const T & v1, const T & v2, const T & v3) {
|
|
_CSet::insert(v0, 0);
|
|
_CSet::insert(v1, 0);
|
|
_CSet::insert(v2, 0);
|
|
_CSet::insert(v3, 0);
|
|
}
|
|
|
|
|
|
class const_iterator {
|
|
friend class PISet<T>;
|
|
|
|
private:
|
|
inline const_iterator(const PISet<T> * v, ssize_t p): parent(v), pos(p) {}
|
|
const PISet<T> * parent;
|
|
ssize_t pos;
|
|
|
|
public:
|
|
typedef T value_type;
|
|
typedef T * pointer;
|
|
typedef T & reference;
|
|
typedef std::ptrdiff_t difference_type;
|
|
typedef std::random_access_iterator_tag iterator_category;
|
|
|
|
inline const_iterator(): parent(0), pos(0) {}
|
|
|
|
inline const T & operator*() const { return parent->pim_index[pos].key; }
|
|
inline const T & operator->() const { return parent->pim_index[pos].key; }
|
|
|
|
inline const_iterator & operator++() {
|
|
++pos;
|
|
return *this;
|
|
}
|
|
inline const_iterator operator++(int) {
|
|
const auto tmp = *this;
|
|
++*this;
|
|
return tmp;
|
|
}
|
|
inline const_iterator & operator--() {
|
|
--pos;
|
|
return *this;
|
|
}
|
|
inline const_iterator operator--(int) {
|
|
const auto tmp = *this;
|
|
--*this;
|
|
return tmp;
|
|
}
|
|
|
|
inline const_iterator & operator+=(const const_iterator & it) {
|
|
pos += it.pos;
|
|
return *this;
|
|
}
|
|
inline const_iterator & operator+=(size_t p) {
|
|
pos += p;
|
|
return *this;
|
|
}
|
|
inline const_iterator & operator-=(const const_iterator & it) {
|
|
pos -= it.pos;
|
|
return *this;
|
|
}
|
|
inline const_iterator & operator-=(size_t p) {
|
|
pos -= p;
|
|
return *this;
|
|
}
|
|
|
|
friend inline const_iterator operator-(size_t p, const const_iterator & it) { return it - p; }
|
|
friend inline const_iterator operator-(const const_iterator & it, size_t p) {
|
|
auto tmp = it;
|
|
tmp -= p;
|
|
return tmp;
|
|
}
|
|
friend inline std::ptrdiff_t operator-(const const_iterator & it1, const const_iterator & it2) { return it1.pos - it2.pos; }
|
|
|
|
friend inline const_iterator operator+(size_t p, const const_iterator & it) { return it + p; }
|
|
friend inline const_iterator operator+(const const_iterator & it, size_t p) {
|
|
auto tmp = it;
|
|
tmp += p;
|
|
return tmp;
|
|
}
|
|
|
|
inline bool operator==(const const_iterator & it) const { return (pos == it.pos); }
|
|
inline bool operator!=(const const_iterator & it) const { return (pos != it.pos); }
|
|
friend inline bool operator<(const const_iterator & it1, const const_iterator & it2) { return it1.pos < it2.pos; }
|
|
friend inline bool operator<=(const const_iterator & it1, const const_iterator & it2) { return it1.pos <= it2.pos; }
|
|
friend inline bool operator>(const const_iterator & it1, const const_iterator & it2) { return it1.pos > it2.pos; }
|
|
friend inline bool operator>=(const const_iterator & it1, const const_iterator & it2) { return it1.pos >= it2.pos; }
|
|
};
|
|
|
|
|
|
inline const_iterator begin() const { return const_iterator(this, 0); }
|
|
inline const_iterator end() const { return const_iterator(this, _CSet::size()); }
|
|
|
|
//! Contructs set from vector of elements
|
|
explicit PISet(const PIVector<T> & values) {
|
|
if (values.isEmpty()) return;
|
|
for (int i = 0; i < values.size_s(); ++i) {
|
|
_CSet::insert(values[i], 0);
|
|
}
|
|
}
|
|
|
|
//! Contructs set from deque of elements
|
|
explicit PISet(const PIDeque<T> & values) {
|
|
if (values.isEmpty()) return;
|
|
for (int i = 0; i < values.size_s(); ++i) {
|
|
_CSet::insert(values[i], 0);
|
|
}
|
|
}
|
|
|
|
typedef T key_type;
|
|
|
|
PISet<T> & operator<<(const T & t) {
|
|
_CSet::insert(t, 0);
|
|
return *this;
|
|
}
|
|
PISet<T> & operator<<(T && t) {
|
|
_CSet::insert(std::move(t), 0);
|
|
return *this;
|
|
}
|
|
PISet<T> & operator<<(const PISet<T> & other) {
|
|
(*(_CSet *)this) << *((_CSet *)&other);
|
|
return *this;
|
|
}
|
|
|
|
//! \~english Tests if element `key` exists in the set.
|
|
//! \~russian Проверяет наличие элемента `key` в массиве.
|
|
inline bool contains(const T & t) const { return _CSet::contains(t); }
|
|
|
|
//! Returns if element "t" exists in this set
|
|
bool operator[](const T & t) const { return _CSet::contains(t); }
|
|
|
|
//! Returns if element "t" exists in this set
|
|
PISet<T> & remove(const T & t) {
|
|
_CSet::remove(t);
|
|
return *this;
|
|
}
|
|
|
|
//! Unite set with "v"
|
|
PISet<T> & unite(const PISet<T> & v) {
|
|
for (const auto & i: v)
|
|
_CSet::insert(i, 0);
|
|
return *this;
|
|
}
|
|
|
|
//! Subtract set with "v"
|
|
PISet<T> & subtract(const PISet<T> & v) {
|
|
for (const auto & i: v)
|
|
_CSet::remove(i);
|
|
return *this;
|
|
}
|
|
|
|
//! Intersect set with "v"
|
|
PISet<T> & intersect(const PISet<T> & v) {
|
|
_CSet::removeWhere([&v](const T & k, uchar) { return !v.contains(k); });
|
|
return *this;
|
|
}
|
|
|
|
//! Unite set with "v"
|
|
PISet<T> & operator+=(const PISet<T> & v) { return unite(v); }
|
|
|
|
//! Unite set with "v"
|
|
PISet<T> & operator|=(const PISet<T> & v) { return unite(v); }
|
|
|
|
//! Subtract set with "v"
|
|
PISet<T> & operator-=(const PISet<T> & v) { return subtract(v); }
|
|
|
|
//! Intersect set with "v"
|
|
PISet<T> & operator&=(const PISet<T> & v) { return intersect(v); }
|
|
|
|
//! Returns content of set as PIVector
|
|
PIVector<T> toVector() const {
|
|
PIVector<T> ret;
|
|
for (const auto & i: *this)
|
|
ret << i;
|
|
return ret;
|
|
}
|
|
|
|
//! Returns content of set as PIDeque
|
|
PIDeque<T> toDeque() const {
|
|
PIDeque<T> ret;
|
|
for (const auto & i: *this)
|
|
ret << i;
|
|
return ret;
|
|
}
|
|
};
|
|
|
|
|
|
//! \relatesalso PISet \brief Returns unite of two sets
|
|
template<typename T>
|
|
PISet<T> operator+(const PISet<T> & v0, const PISet<T> & v1) {
|
|
PISet<T> ret(v0);
|
|
ret.unite(v1);
|
|
return ret;
|
|
}
|
|
|
|
//! \relatesalso PISet \brief Returns subtraction of two sets
|
|
template<typename T>
|
|
PISet<T> operator-(const PISet<T> & v0, const PISet<T> & v1) {
|
|
PISet<T> ret(v0);
|
|
ret.subtract(v1);
|
|
return ret;
|
|
}
|
|
|
|
//! \relatesalso PISet \brief Returns unite of two sets
|
|
template<typename T>
|
|
PISet<T> operator|(const PISet<T> & v0, const PISet<T> & v1) {
|
|
PISet<T> ret(v0);
|
|
ret.unite(v1);
|
|
return ret;
|
|
}
|
|
|
|
//! \relatesalso PISet \brief Returns intersetion of two sets
|
|
template<typename T>
|
|
PISet<T> operator&(const PISet<T> & v0, const PISet<T> & v1) {
|
|
PISet<T> ret(v0);
|
|
ret.intersect(v1);
|
|
return ret;
|
|
}
|
|
|
|
|
|
template<typename Type>
|
|
inline PICout operator<<(PICout s, const PISet<Type> & v) {
|
|
s.space();
|
|
s.saveAndSetControls(0);
|
|
s << "{";
|
|
bool first = true;
|
|
for (const auto & i: v) {
|
|
if (!first) s << ", ";
|
|
first = false;
|
|
s << i;
|
|
}
|
|
s << "}";
|
|
s.restoreControls();
|
|
return s;
|
|
}
|
|
|
|
#endif // PISET_H
|