Search code examples
c++stlsetbinary-treered-black-tree

How can I get relative index of std::set?


I've faced one problem recently. I want to get the relative index of std::set element. For example, if std::set stores {1, 2, 4, 6, 9, 15}, and I want to find element {4} and get its relative index {2} efficiently. Of course, I can write std::distance(myset.begin(), myiterator), but the complexity of this operation is O(n*logn). If I had access to real red-black tree of std::set, I would just run rb_tree_node_pos(see below), which is O(logn).That is exactly the relative index. Does anyone know how can I get real tree? Here's code example:

#include <iostream>
#include <set>
using namespace std ;
int rb_tree_node_pos(rb_tree_node *node) {
  //function that finds relative index of tree node
  if (node->parent==NULL) return rb_tree_size(node->left) ;
  else return rb_tree_node_pos(node->parent)+rb_tree_size(node->left)+1 ;_
}
int main () {
  set<int> myset ;
  //... reading some data in myset
  int find_int ;
  cin >> find_int ;
  set<int>::iterator myit=myset.find(find_int) ;
  int find_index=distance(myset.begin(), myit) ; // O(n*log(n)), to slow!!!
  find_index=rb_tree_node_pos(myit->get_rb_tree()) ; // that's O(logn)
  cout << find_index << endl ;
  return 0 ;
}

In general I want data structure that will maintain following operations: 1. insert element, 2. delete element, 3.print out relative index of element. I think there is a way to 'dig' it from STL.


Solution

  • Thanks to @Fanael , who found the solution! We can implement this data structure using GNU Policy Based Data Structures(PBDS). Here's the code example:

    #include <iostream>
    #include <ext/pb_ds/assoc_container.hpp>
    #include <ext/pb_ds/tree_policy.hpp>
    
    using namespace std;
    using namespace __gnu_pbds;
    
    typedef
    tree<
      int,
      null_type,
      less<int>,
      rb_tree_tag,
      tree_order_statistics_node_update>
    ordered_set;
    
    int main()
    {
      ordered_set myset;
      //....reading some data to myset
      int find_int ;
      cin >> find_int ;
      find_index=myset.order_of_key(find_int) ;
      cout << find_index << endl ;
      return 0;
    }
    

    You can learn more about GNU PBDS from here and here. Thanks to everyone who helped!