Open In App

Policy based data structures in g++

Last Updated : 25 Jan, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

The g++ compiler also supports some data structures that are not part of the C++ standard library. Such structures are called policy-based data structures. These data structures are designed for high-performance, flexibility, semantic safety, and conformance to the corresponding containers in std.
To use these structures, the following lines must be added to the code: 
 

C++




#include <ext/pb_ds/assoc_container.hpp>
using namespace __gnu_pbds;


For example, following is a code showing a policy-based data structure that is like set, it can add/remove elements, can find the number of elements less than x, kth smallest element etc in O(logn) time. It can also be indexed like an array. The specialty of this set is that we have access to the indices that the elements would have in a sorted array. If the element does not appear in the set, we get the position that the element would have in the set.
 

C++




// Program showing a policy-based data structure.
#include <ext/pb_ds/assoc_container.hpp> // Common file
#include <ext/pb_ds/tree_policy.hpp>
#include <functional> // for less
#include <iostream>
using namespace __gnu_pbds;
using namespace std;
 
// a new data structure defined. Please refer below
// GNU link : https://goo.gl/WVDL6g
typedef tree<int, null_type, less<int>, rb_tree_tag,
             tree_order_statistics_node_update>
    ordered_set;
 
// Driver code
int main()
{
    ordered_set p;
    p.insert(5);
    p.insert(2);
    p.insert(6);
    p.insert(4);
 
    // value at 3rd index in sorted array.
    cout << "The value at 3rd index ::"
         << *p.find_by_order(3) << endl;
 
    // index of number 6
    cout << "The index of number 6::" << p.order_of_key(6)
         << endl;
 
    // number 7 not in the set but it will show the
    // index number if it was there in sorted array.
    cout << "The index of number seven ::"
         << p.order_of_key(7) << endl;
 
    return 0;
}


Output

The value at 3rd index ::6
The index of number 6::3
The index of number seven ::4

NOTE: Both the functions order_of_key and find_by_order work in logarithmic time.

NOTE (FOR WINDOW USERS) : Window users might face problem importing pbds library . To fix it follow the following steps:

         Step 1: Go to directory  where MinGW is installed.

         Step 2: Navigate to \lib\gcc\mingw32\8.2.0\include\c++\ext\pb_ds\detail\resize_policy

         Step 3: Rename “hash_standard_resize_policy_imp.hpp0000644” to “hash_standard_resize_policy_imp.hpp”

In order to insert multiple copies of the same element in the ordered set, a simple approach is to replace the following line,

typedef tree<int , null_type, less<int> , rb_tree_tag , tree_order_statistics_node_update> ordered_set;

With

typedef tree<int , null_type ,  less_equal<int> , rb_tree_tag , tree_order_statistics_node_update> ordered_multiset

C++




// Program showing a policy-based data structure.
#include <ext/pb_ds/assoc_container.hpp> // Common file
#include <ext/pb_ds/tree_policy.hpp>
#include <functional> // for less
#include <iostream>
using namespace __gnu_pbds;
using namespace std;
 
// a new data structure defined. Please refer below
// GNU link : https://goo.gl/WVDL6g
typedef tree<int, null_type, less_equal<int>, rb_tree_tag,
             tree_order_statistics_node_update>
    ordered_multiset;
 
// Driver code
int main()
{
    ordered_multiset p;
    p.insert(5);
    p.insert(5);
    p.insert(5);
    p.insert(2);
    p.insert(2);
    p.insert(6);
    p.insert(4);
 
    for (int i = 0; i < (int)p.size(); i++) {
 
        cout << "The element present at the index " << i
             << " is ";
 
        // Print element present at the ith index
        cout << *p.find_by_order(i) << ' ';
        cout << '\n';
    }
 
    return 0;
}


Output

The element present at the index 0 is 2 
The element present at the index 1 is 2 
The element present at the index 2 is 4 
The element present at the index 3 is 5 
The element present at the index 4 is 5 
The element present at the index 5 is 5 
The element present at the index 6 is 6 

However, the above approach is not recommended because the G++ Policy-Based Data structure is not designed for storing elements in a strict weak ordering, so using less_equal with it can cause undefined behavior, such as std::find giving incorrect output and longer search times. Another approach is to instead store the elements as pairs where the first element is the value of the element, and the second element of the pair is the index at which it was found in the array. The source code below demonstrates how to use this approach alongside with other methods available in the ordered set.

C++




// Program showing a policy-based data structure.
#include <ext/pb_ds/assoc_container.hpp> // Common file
#include <ext/pb_ds/tree_policy.hpp>
#include <functional> // for less
#include <iostream>
using namespace __gnu_pbds;
using namespace std;
 
// a new data structure defined. Please refer below
// GNU link : https://goo.gl/WVDL6g
typedef tree<pair<int, int>, null_type,
             less<pair<int, int> >, rb_tree_tag,
             tree_order_statistics_node_update>
    ordered_multiset;
 
// Driver code
int main()
{
    ordered_multiset p;
 
    // During insertion, use {VAL, IDX}
    p.insert({ 5, 0 });
    p.insert({ 5, 1 });
    p.insert({ 5, 2 });
    p.insert({ 2, 3 });
    p.insert({ 2, 4 });
    p.insert({ 6, 5 });
    p.insert({ 4, 6 });
 
    for (int i = 0; i < (int)p.size(); i++) {
 
        cout << "The element present at the index " << i
             << " is ";
 
        // Print element present at the ith index
        // Use .first to get the actual value
        cout << p.find_by_order(i)->first << ' ';
        cout << '\n';
    }
 
    cout << "\nDeleting element of 2\n\n";
 
    // Whenever searching use {VAL, 0}       for lower_bound
    //                        {VAL, IDX}     for find
    //                        {VAL, INT_MAX} for upper_bound
    p.erase(p.lower_bound({ 2, 0 }));
 
    for (int i = 0; i < (int)p.size(); i++) {
 
        cout << "The element present at the index " << i
             << " is ";
 
        cout << p.find_by_order(i)->first << ' ';
        cout << '\n';
    }
 
    return 0;
}


Output

The element present at the index 0 is 2 
The element present at the index 1 is 2 
The element present at the index 2 is 4 
The element present at the index 3 is 5 
The element present at the index 4 is 5 
The element present at the index 5 is 5 
The element present at the index 6 is 6 

Deleting element of 2

The element present at the index 0 is 2 
The element present at the index 1 is 4 
The element present at the index 2 is 5 
The element present at the index 3 is 5 
The element present at the index 4 is 5 
The element present at the index 5 is 6 


Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads