Cod sursa(job #910778)

Utilizator freak93Adrian Budau freak93 Data 11 martie 2013 01:15:50
Problema Hashuri Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 5.19 kb
#include <iostream>
#include <fstream>
#include <algorithm>
#include <tr1/functional>

template<class DataType>
class HashSet {
  public:
    HashSet(const size_t &bits = 4) {
        Initialize(1 << bits);
    }

    ~HashSet() {
        delete[] data_;
        delete[] data_type_;
    }

    class Iterator : public std::iterator<std::input_iterator_tag, DataType> {
      public:
        Iterator(DataType* const data, char* const data_type):
          data_(data),
          data_type_(data_type) {
        }

        Iterator(const Iterator& that):
          data_(that.data_),
          data_type_(that.data_type_) {
        }

        bool Empty() const {
            return *data_type_ == kEmptyElement;
        }

        bool Filled() const {
            return *data_type_ == kFilledElement;
        }

        Iterator& operator=(const DataType& that) {
            *data_ = that;
            *data_type_ = kFilledElement;
            return *this;
        }

        bool operator!=(const Iterator& that) const {
            return data_ != that.data_ || data_type_ != that.data_type_;
        }

        bool operator!=(const DataType& that) const {
            return *data_ != that;
        }

        bool operator==(const DataType& that) const {
            return *data_ == that;
        }

        const DataType& operator*() const {
            return *data_;
        }

      private:
        enum {
            kEmptyElement = 0,
            kErasedElement = 1,
            kFilledElement = 2,
        };
       
        friend class HashSet;

        DataType *data_;
        char *data_type_;
    };

    Iterator Find(const DataType& data) {
        Iterator it = PointTo(data);
        while (!it.Empty() && it != data)
            it = PointToNext(it);

        if (it.Empty())
            return End();
        return it;
    }


    std::pair<Iterator, bool> Insert(const DataType& element) {
        Iterator it = Find(element);
        if (it != End())
            return std::pair<Iterator, bool>(it, false);
        it = PointTo(element);
        while (it.Filled()) {
            it = PointToNext(it);
        }

        if (it.Empty())
            ++non_empty_elements_;

        it = element;

        if (non_empty_elements_ == maximum_capacity_) {
            Grow();
            return std::pair<Iterator, bool>(Find(element), true);
        }

        return std::pair<Iterator, bool>(it, true);
    }

    template<class InputIterator>
    size_t Insert(InputIterator first, InputIterator last) {
        size_t inserted = 0;
        while (first != last) {
            if (Insert(*first).second)
                ++inserted;
        }

        return inserted;
    }

    bool Erase(const DataType& element) {
        Iterator it = Find(element);

        if (it != End()) {
            Erase(it);
            return true;
        }

        return false;
    }

    bool Erase(const Iterator& iterator) {
        *(iterator.data_)  = DataType();
        *(iterator.data_type_) = kErasedElement;

        filled_elements_--;

        return true;
    }

    Iterator Begin() {
        return Iterator(data_, data_type_);
    }

    Iterator End() {
        return Iterator(data_ + size_, data_type_ + size_);
    }

  private:
    enum {
        kEmptyElement = 0,
        kErasedElement = 1,
        kFilledElement = 2,
    };

    static const double kLoadFactor;
    static const std::tr1::hash<DataType> kHashFunction;

    void Initialize(const int &size) {
        size_ = size;
        maximum_capacity_ = kLoadFactor * size;
        non_empty_elements_ = 0;
        filled_elements_ = 0;

        data_ = new DataType[size];
        data_type_ = new char[size];
        std::fill_n(data_type_, size, kEmptyElement);
    }

    Iterator PointTo(const DataType& data) {
        size_t position = kHashFunction(data);
        return Iterator(data_ + position, data_type_ + position);
    }

    Iterator PointToNext(const Iterator& current) {
        size_t position = current.data_ - data_;
        position = (position * 5 + 1) & (size_ - 1);

        return Iterator(data_ + position, data_type_ + position);
    }

    void Grow() {
        DataType *old_data = data_;
        char* old_data_type = data_type_;

        Iterator old_begin = Begin(), old_end = End();

        Initialize(size_ * 2);

        Insert(old_begin, old_end);

        delete[] old_data;
        delete[] old_data_type;
    }

    size_t size_;
    size_t maximum_capacity_;
    size_t non_empty_elements_;
    size_t filled_elements_;

    DataType *data_;

    // FIXME: we are now using 8 bits for information for which we only need 2 bits, optimize a little
    char *data_type_;
};

template<class DataType>
const double HashSet<DataType>::kLoadFactor = 0.75;

template<class DataType>
const std::tr1::hash<DataType> HashSet<DataType>::kHashFunction;

using namespace std;

int main() {
    ifstream cin("hashuri.in");
    ofstream cout("hashuri.out");

    int N; cin >> N;
    HashSet<int> H;

    for (int i = 0; i < N; ++i) {
        int type, value;
        cin >> type>> value;
        if (type == 1)
            H.Insert(value);
        if (type == 2)
            H.Erase(value);
        if (type == 3)
            cout << bool(H.Find(value) != H.End()) << "\n";
    }
}