Ordered Containers

Summary

In this post, I will introduce the map and priority_queue in c++ STL.

Why Ordered Containers

Unlike the easy version unordered_map, in map, key values are generally used to sort. Thanks to the binary search tree, map has good performance in search and erase elements $(log(n))$.

Constructor

The following codes are self-explained.

 
// Example of usage of priority_queue
// override < is a easy solution
struct T {
        int t, x, y;
        T(int a, int b, int c) : t (a), x (b), y (c){}
        bool operator< (const T &d) const {return t > d.t;}
    };

void temp(vector<vector<int>> & grid) {
        int N = grid.size (), res = 0;
        priority_queue pq;
        pq.push(T(grid[0][0], 0, 0));
}
#include <iostream>
#include <map>
#include <set>

class Compare {
public:
    bool operator() (int const & a, int const &b) const {
        return a > b;
    }
};

int main(){
    // class based
    Compare compare_instance;
    // lambda based
    auto comp = [](int i, int j){return i > j;};
    map<int, std::string, decltype(comp)> int2Str(comp);
    // map<int, std::string, Compare> int2Str(compare_instance);
    multiset<int, decltype(comp)> int_set(comp);
    unordered_map<int, string> int2str_no_order = {{5, "five"}, {1, "one"}, {4, "four"}, {3, "three"},
            {2, "two"}, {7, "seven"}, {6, "six"} };
    for (auto k_v : int2str_no_order) {
        int2Str[k_v.first] = k_v.second;
        int_set.insert(k_v.first);
    }

    // can repeat
    int2Str.insert(make_pair(7, "seven"));
    int_set.insert(7);
    for (auto p : int2Str) {
        cout << "{" << p.first << "," << p.second << "} ";
    }
    // {7,seven} {6,six} {5,five} {4,four} {3,three} {2,two} {1,one}
    cout << endl;
    for (auto p : int_set) {
        cout << p << " ";
    }
    // 7 7 6 5 4 3 2 1
    return 0;
}

Search Funcitons

Ordered containers are optimized for searching in $(log(n))$.

Functions
ordAssCont.count(key) Returns the number of values with the key.
ordAssCont.find(key) Returns the iterator of key in ordAssCont. If there is no key in ordAssCont it returns ordAssCont.end().
ordAssCont.lower_bound(key) Returns the iterator to the first key in ordAssCont in which key would be inserted.
ordAssCont.upper_bound(key) Returns the iterator to the last position of key in ordAssCont in which key would be inserted.
ordAssCont.equal_range(key) Returns the range ordAssCont.lower bound(key) and ordAssCont.upper_bound(key) in a std::pair.

The following codes are self-explained.

#include <iostream>
#include <set>

int main(){
  std::multiset<int> mySet{3, 1, 5, 3, 4, 5, 1, 4, 4, 3, 2, 2, 7, 6, 4, 3, 6};

  for (auto s: mySet) std::cout << s << " "; // 1 1 2 2 3 3 3 3 4 4 4 4 5 5 6 6 7
  std::cout<<"\n";

  mySet.erase(mySet.lower_bound(4), mySet.upper_bound(4));
  for (auto s: mySet) std::cout << s << " "; // 1 1 2 2 3 3 3 3 5 5 6 6 7
  std::cout<<"\n";

  std::cout << mySet.count(3) << std::endl; // 4
  std::cout << *mySet.find(3) << std::endl; // 3
  std::cout << *mySet.lower_bound(3) << std::endl; // 3
  std::cout << *mySet.upper_bound(3) << std::endl; // 5
  auto pair= mySet.equal_range(3);
  std::cout << "(" << *pair.first << "," << *pair.second << ")"; // (3,5)

  return 0;
}

Leave a Reply

Your email address will not be published. Required fields are marked *