【数据结构】静态map

map可以动态进行插入删除等操作,但其常数太高了。

如果只用一个有序数组来存储的话,那么可以提供更好的查询复杂度的常数,同时在构建的时候由于不需要保存额外的信息所以非常节约内存:需要小心的是这个map只能找到第一个重复的元素,如果需要进行覆盖操作的话,一般还是得使用BST去做。当然也可以get之后对其进行赋值,但是要小心这样会破坏掉数组的有序性,必须要sort之后才能重新使用。如果遇到这种需要替换的情况的话,还是得弄一个辅助vector比较简单。也就是下文中使用两倍空间的做法(毕竟要优先保证时间复杂度)

这个数据结构比map要快很多,同时非常节约空间,代价是在sort之后不能进行任何修改操作,只适用于查询比修改多非常多的情况。它甚至不能去重,建立时在数据外侧自己想办法去重或者用下文的双倍空间的版本吧。

这个本身就是定制的高速数据结构,要非常小心使用

简单版本的,直接sort,省去了inplace_merge的额外空间。

template <class key_type, class value_type>
struct const_map {
  private:
    const value_type empty_value = default_value<value_type>::empty_value;
    const value_type min_value = default_value<value_type>::min_value;

    vector<pair<key_type, value_type>> vec;
    int vec_sorted_len;

    decltype (vec.begin()) find (const key_type& key) {
        auto it = lower_bound (key);
        if (it == vec.end() || it->first != key) {
            return vec.end();
        }
        return it;
    }

  public:
    void clear() {
        vec.clear();
    }

    void reserve (int n) {
        vec.reserve (n);
    }

    void sort() {
        std::sort (vec.begin(), vec.end());
    }

    int count (const key_type& key) {
        auto it = find (key);
        if (it == vec.end()) {
            return 0;
        }
        return 1;
    }

    const value_type& get_value (const key_type& key) {
        auto it = find (key);
        if (it == vec.end()) {
            return empty_value;
        }
        return it->second;
    }

    void set_value (const key_type& key,  const value_type& value) {
        vec.push_back (make_pair (key, value));
    }

    decltype (vec.begin()) lower_bound (const key_type& key) {
        return std::lower_bound (vec.begin(), vec.end(), make_pair (key, min_value));
    }

    decltype (vec.begin()) begin () {
        return vec.begin();
    }

    decltype (vec.begin()) end () {
        return vec.end();
    }

};

下面这个好像是画蛇添足的版本,略微优化了一点点sort操作的复杂度,但引入了很多不必要的东西。

template<typename>
struct default_value;

template<>
struct default_value<int> {
    static constexpr int empty_value = 0;
    static constexpr int min_value = -INF;
    static constexpr int max_value = INF;
};

template<>
struct default_value<ll> {
    static constexpr ll empty_value = 0LL;
    static constexpr ll min_value = -LINF;
    static constexpr ll max_value = LINF;
};

template <class key_type, class value_type>
struct const_map {
  private:
    const value_type empty_value = default_value<value_type>::empty_value;
    const value_type min_value = default_value<value_type>::min_value;

    vector<pair<key_type, value_type>> vec;
    int vec_sorted_len;

    decltype (vec.begin()) find (const key_type& key) {
        auto it = lower_bound (vec.begin(), vec.begin() + vec_sorted_len, make_pair (key, min_value));
        if (it == vec.begin() + vec_sorted_len || it->first != key) {
            it = vec.end();
        }
        return it;
    }

  public:
    void clear() {
        vec.clear();
        vec_sorted_len = 0;
    }

    void sort() {
        std::sort (vec.begin() + vec_sorted_len, vec.end());
        std::inplace_merge (vec.begin(), vec.begin() + vec_sorted_len, vec.end());
        vec_sorted_len = vec.size();
    }

    int count (const key_type& key) {
        auto it = find (key);
        if (it != vec.end()) {
            return 1;
        }
        return 0;
    }

    const value_type& get_value (const key_type& key) {
        auto it = find (key);
        if (it != vec.end()) {
            return it->second;
        }
        return empty_value;
    }

    void set_value (const key_type& key,  const value_type& value) {
        vec.push_back (make_pair (key, value));
    }

    const value_type& Get (const key_type& key) {
        return get_value (key);
    }

    void Set (const key_type& key,  const value_type& value) {
        set_value (key, value);
    }

};

初代是下面这个,容易看出来是怎么运行的。

struct my_map {
    vector<pair<pii, int>> vec;


    void clear() {
        vec.clear();
    }

    int count (const pii & key) {
        auto it = lower_bound (vec.begin(), vec.end(), make_pair (key, -INF));
        return it == vec.end() ? 0 : it->first == key ? 1 : 0;
    }

    void init() {
        sort (vec.begin(), vec.end());
        vec.resize (unique (vec.begin(), vec.end()) - vec.begin());
    }

    void insert (const pii & key, int value) {
        vec.push_back ({key, value});
    }

    int get (const pii & key) {
        auto it = lower_bound (vec.begin(), vec.end(), make_pair (key, -INF));
        return it ->second;
    }

};

这里还需要研究一下方括号运算符、for-each使用的迭代器。等的写法,使其可以完全替代map。

TODO:无序的版本。

一个可以使用方括号的方案,但是实际上非常多限制,时间和空间都有一点浪费,还容易出bug,记得使用带有序意义的方法之前都要init:

template<typename>
struct default_value;

template<>
struct default_value<int> {
    static constexpr int empty_value = 0;
    static constexpr int min_value = -INF;
    static constexpr int max_value = INF;
};


template <class _Key, class _Tp>
struct my_map {
    typedef _Key key_type;
    typedef _Tp data_type;
    data_type data_type_empty_value = default_value<data_type>::empty_value;
    data_type data_type_min_value = default_value<data_type>::min_value;

    typedef pair<key_type, data_type> node_type;

    vector<node_type> vec, temp_vec;


    void clear() {
        vec.clear();
        temp_vec.clear();
    }

    int count (const pii & key) {
        auto it = lower_bound (vec.begin(), vec.end(), make_pair (key, data_type_min_value));
        return it == vec.end() ? 0 : it->first == key ? 1 : 0;
    }

    void init() {
        sort (vec.begin(), vec.end());
        sort (temp_vec.begin(), temp_vec.end());
        auto vec_it = vec.begin();
        auto temp_vec_it = temp_vec.begin();

        vector<node_type> result_vec;
        while (vec_it != vec.end() || temp_vec_it != temp_vec.end()) {
            if (vec_it == vec.end()) {
                result_vec.push_back (*temp_vec_it);
                ++temp_vec_it;
                continue;
            }
            if (temp_vec_it == temp_vec.end()) {
                result_vec.push_back (*vec_it);
                ++vec_it;
                continue;
            }
            if (vec_it->first > temp_vec_it ->first) {
                result_vec.push_back (*temp_vec_it);
                ++temp_vec_it;
                continue;
            }
            if (vec_it->first < temp_vec_it ->first) {
                result_vec.push_back (*vec_it);
                ++vec_it;
                continue;
            }
            result_vec.push_back (*temp_vec_it);
            ++vec_it;
            ++temp_vec_it;
            continue;
        }
        vec = result_vec;
        temp_vec.clear();
    }

    const data_type& get_value (const key_type& key) {
        if (count (key) > 0) {
            auto it = lower_bound (vec.begin(), vec.end(), make_pair (key, data_type_min_value));
            return it->second;
        }
        return data_type_empty_value;
    }

    // 为了节省维持map的复杂度所带来的常数,使用上的特殊约定是必须的
    void set_value (const key_type& key,  const data_type& data) {
        // 新的值要在init之后才会生效
        // 如果原本已有这个key,那么可以覆盖
        // 如果在init之前,多次插入同一个key,会出现奇怪的事情
        temp_vec.push_back (make_pair (key, data));
    }

    // 为了节省维持map的复杂度所带来的常数,使用上的特殊约定是必须的
    data_type& operator[] (const key_type& key) {
        if (count (key) > 0) {
            auto it = lower_bound (vec.begin(), vec.end(), make_pair (key, data_type_min_value));
            // 这里的方括号运算符很诡异,返回的是原本的一个拷贝,新的值要在init之后才会生效
            // 如果原本已有这个key,那么可以覆盖
            // 如果在init之前,多次插入同一个key,会出现奇怪的事情
            temp_vec.push_back (make_pair (key, it->second));
            return temp_vec.back().second;
        }
        temp_vec.push_back (make_pair (key, data_type_empty_value));
        return temp_vec.back().second;
    }

};

下面的方法通过拷贝vec去掉归并来提高速度,代价是牺牲空间:


template<typename>
struct default_value;

template<>
struct default_value<int> {
    static constexpr int empty_value = 0;
    static constexpr int min_value = -INF;
    static constexpr int max_value = INF;
};


template <class _Key, class _Tp>
struct my_map {
    typedef _Key key_type;
    typedef _Tp data_type;
    data_type data_type_empty_value = default_value<data_type>::empty_value;
    data_type data_type_min_value = default_value<data_type>::min_value;

    typedef pair<key_type, data_type> node_type;

    vector<node_type> vec, temp_vec;


    void clear() {
        vec.clear();
        temp_vec.clear();
    }

    int count (const pii & key) {
        auto it = lower_bound (vec.begin(), vec.end(), make_pair (key, data_type_min_value));
        return it == vec.end() ? 0 : it->first == key ? 1 : 0;
    }

    void init() {
        sort (temp_vec.begin(), temp_vec.end());
        vec = temp_vec;
    }

    const data_type& get_value (const key_type& key) {
        if (count (key) > 0) {
            auto it = lower_bound (vec.begin(), vec.end(), make_pair (key, data_type_min_value));
            return it->second;
        }
        return data_type_empty_value;
    }

    // 为了节省维持map的复杂度所带来的常数,使用上的特殊约定是必须的
    void set_value (const key_type& key,  const data_type& data) {
        // 新的值要在init之后才会生效
        // 如果原本已有这个key,那么可以覆盖
        // 如果在init之前,多次插入同一个key,会出现奇怪的事情
        temp_vec.push_back (make_pair (key, data));
    }

    // 为了节省维持map的复杂度所带来的常数,使用上的特殊约定是必须的
    data_type& operator[] (const key_type& key) {
        if (count (key) > 0) {
            auto it = lower_bound (vec.begin(), vec.end(), make_pair (key, data_type_min_value));
            // 这里的方括号运算符很诡异,返回的是原本的一个拷贝,新的值要在init之后才会生效
            // 如果原本已有这个key,那么可以覆盖
            // 如果在init之前,多次插入同一个key,会出现奇怪的事情
            temp_vec.push_back (make_pair (key, it->second));
            return temp_vec.back().second;
        }
        temp_vec.push_back (make_pair (key, data_type_empty_value));
        return temp_vec.back().second;
    }

};

然而既然是CP,最推荐的方法是下面的:

template<typename>
struct default_value;

template<>
struct default_value<int> {
    static constexpr int empty_value = 0;
    static constexpr int min_value = -INF;
    static constexpr int max_value = INF;
};

template< class T >
using remove_reference_t = typename remove_reference<T>::type;

template <class _Key, class _Tp>
struct my_map {
    typedef _Key key_type;
    typedef _Tp data_type;
    data_type data_type_empty_value = default_value<data_type>::empty_value;
    data_type data_type_min_value = default_value<data_type>::min_value;

    typedef pair<key_type, data_type> node_type;

    vector<node_type> vec;
    int vec_sorted_len;


    void clear() {
        vec.clear();
        vec_sorted_len = 0;
    }

    int count (const pii & key) {
        auto it = lower_bound (vec.begin(), vec.begin() + vec_sorted_len, make_pair (key, data_type_min_value));
        return it != vec.end() && it->first == key;
    }

    void sort() {
        std::sort (vec.begin() + vec_sorted_len, vec.end());
        inplace_merge (vec.begin(), vec.begin() + vec_sorted_len, vec.end());
        vec_sorted_len = vec.size();
    }

    const data_type& get_value (const key_type& key) {
        if (count (key) > 0) {
            auto it = lower_bound (vec.begin(), vec.begin() + vec_sorted_len, make_pair (key, data_type_min_value));
            return it->second;
        }
        return data_type_empty_value;
    }

    void set_value (const key_type& key,  const data_type& data) {
        vec.push_back (make_pair (key, data));
    }

    const data_type& G (const key_type& key) {
        return get_value (key);
    }

    void S (const key_type& key,  const data_type& data) {
        set_value (key, data);
    }

};
posted @ 2023-12-04 01:35  purinliang  阅读(31)  评论(0编辑  收藏  举报