1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

STL Containers With Examples

Discussion in 'C++' started by BiplabKamal, Jun 3, 2016.

  1. All container classes are part of std name space. Most of the member functions of container classes are common and have common functionality. The decision of which container to use for specif need does not generally depend on the functionality of a container but the efficiency of some of it’s members. This is specifically true for sequence containers which provide different tradeoffs in complexities to insert/delete/access it’s elements. Learning STL will be effective only when you write programs using them. So I will not go behind every member of each container but give a brief overview of major container classes with simple examples. Complete details of each class you should consult the STL reference documents.

    Array class (std::array)



    Header: <array>
    Declaration: template < class T, size_t N > class array;

    Arrays are fixed size sequence container. It takes the element type and number of elements in the array as template arguments. The size of the sequence is fixed at compile time. So no memory management and dynamic allocation involved. This class does not store any extra data other than the sequence of elements. It only adds layer of functions so that it works as a container. This is different than other containers whose size is dynamically changed. This has all the property of normal language defined array declared with bracket ([]) syntax. Zero size containers are valid but they should not be dereferenced.

    Example:std::array

    Code:
    #include<iostream>
    #include<array>
    using namespace std;
    int main()
    {
        //Creating an array container with braced initializer
        std::array<int,10> myarray{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        //Accessing elements with [] operator
        for (int i = 0;i < 10;++i)
            myarray[i] = myarray[i] * 2;
        //Accessing elements using the pointer to the underlying array
        auto data = myarray.data();
        for (int i = 0;i < 10;++i)
            *(data + i) += 1;
        // Accessing elements with at() function
        for (int i = 0;i < 10;++i)
            myarray.at(i) *=10;
        //Acdessing the first element
        cout << "The first element:" << myarray.front()<<endl;
        //accessing the last element
        cout << "The last element:" << myarray.back()<<endl;
        for (const int val : myarray)
            std::cout << val << " ";
        std::cout << std::endl;
        return 0;
    }
    
    Output:
    Code:
    The first element:1
    The last element:10
    1 2 3 4 5 6 7 8 9 10
    

    Vector class (std::array)



    Header: <vector>
    Declaration: template < class T, class Alloc = allocator<T> > class vector;

    The instance of vector template class is a sequence container of a given data type. The elements are stored contiguously in memory. It stores the elements similar to a normal array but it can dynamically re-size the array by allocating and deallocating memory. To optimize the reallocation it allocates extra memory so that it does not need to reallocate memory every time an element is added. If you know the minimum number of elements it is better to allocate that by calling the reserve() method of the vector so that no reallocation is needed until the number of elements exceed the minimum number. Like array container, vector elements can be accessed directly using [] operator and offset on a regular pointer to it’s elements. Vector is very efficient in accessing its elements with array index. Adding elements at the end is efficient but inserting element in between is costly compared to other containers. This is because every time inserting an element require some elements to be moved. Also resizing has an overhead which is optimized by intelligent memory allocation.

    Example: std::vector

    Code:
    #include<iostream>
    #include<vector>
    using namespace std;
    int main()
    {
        //Creating a vector container with braced initializer
        std::vector<int> myvector{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
        //Accessing elements with [] operator
        for (int i = 0;i < 10;++i)
            myvector[i] = myvector[i] * 2;
        //Accessing elements using the pointer to the underlying array
        auto data = myvector.data();
        for (int i = 0;i < 10;++i)
            *(data + i) += 1;
        // Accessing elements with at() function
        for (int i = 0;i < 10;++i)
            myvector.at(i) *= 10;
        //Accessing the first element
        cout << "The first element:" << myvector.front() << endl;
        //Accessing the last element
        cout << "The last element:" << myvector.back() << endl;
        auto beginItr = myvector.begin();
        auto endItr = myvector.end();
        //Accessing elements using iterator
        while (beginItr != endItr)
        {
            std::cout << *beginItr << " ";
            ++beginItr;
        }
        std::cout << std::endl;
        return 0;
    }
    
    Output:
    Code:
    The first element:30
    The last element:210
    30 50 70 90 110 130 150 170 190 210
    

    List class (std::list)



    Header: <list>
    Declaration: template < class T, class Alloc = allocator<T> > class list;

    List is a sequence container which stores the elements in a doubly linked list. The sequence of the elements is maintained by associating to each element of a link to the preceding element and another link to the following element. So each element size is increased by 2 pointers. But this has advantage of constant time to insert or remove elements when you have an iterator of the sequence. It also allows to iterate both direction with constant time. On the other hand you cannot access elements directly. You have to use iterator and move it to reach a desired position to access the element.

    Example of std::list

    Code:
    #include<iostream>
    #include<list>
    using namespace std;
    int main()
    {
        //Creating a list container with braced initializer
        std::list<int> mylist{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        //Accessing elements with iterator
        auto beginItr = mylist.begin();
        auto endItr = mylist.end();
        while (beginItr != endItr)
        {
            *beginItr *= 2;
            ++beginItr;
        }
        //Acdessing the first element
        cout << "The first element:" << mylist.front()<<endl;
        //accessing the last element
        cout << "The last element:" << mylist.back()<<endl;
        for (const int val : mylist)
            std::cout << val << " ";
        std::cout << std::endl;
        return 0;
    }
    
    Output:
    Code:
    The first element:2
    The last element:20
    2 4 6 8 10 12 14 16 18 20
    

    Deque class (std::deque)



    Header: <deque>
    Declaration: template < class T, class Alloc = allocator<T> > class deque;

    Template container class std::deque (double-ended-queue) is a sequence container and behaves similar to the std::vector class with the difference that deque can grow/shrink in both direction. You can add/remove elements to/from both the ends. Unlike vector it does not guarantee to store all the elements in contiguous memory location. That’s why accessing an element by using offset to a pointer to another element is not safe. This also makes the internal implementation of deque more complex than vector but it helps it to grow more efficiently in some scenarios, specially when having very long sequence and reallocation is expensive.

    Example of std::deque

    Code:
    #include<iostream>
    #include<deque>
    using namespace std;
    int main()
    {
        //Creating a deque container with braced initializer
        std::deque<int> mydeque{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
        //Adding elements at the end
        mydeque.emplace_back(11);
        //Adding elements at the beginning
        mydeque.emplace_front(0);
        //Accessing elements with [] operator
        for (int i = 0;i <mydeque.size();++i)
            mydeque[i] = mydeque[i] * 2;
        
        // Accessing elements with at() function
        for (int i = 0;i < mydeque.size();++i)
            mydeque.at(i) *= 10;
        //Accessing the first element
        cout << "The first element:" << mydeque.front() << endl;
        //Accessing the last element
        cout << "The last element:" << mydeque.back() << endl;
        //Getting reverse iterators
        auto rbeginItr = mydeque.rbegin();
        auto rendItr = mydeque.rend();
        //Accessing elements using reverse iterator
        cout << "Elements in reverse order: ";
        while (rbeginItr != rendItr)
        {
            std::cout << *rbeginItr << " ";
            ++rbeginItr;
        }
        std::cout << std::endl;
        return 0;
    }
    
    Output:
    Code:
    The first element:0
    The last element:220
    Elements in reverse order: 220 200 180 160 140 120 100 80 60 40 20 0
    

    Forward_list class (std::forward_list)



    Header: <forward_list>
    Declaration: template < class T, class Alloc = allocator<T> > class forward_list;

    forward_list container class is a sequence container which stores the elements in a singly-linked list. Each element may be stored in different and unrelated memory locations. The sequence of the elements is maintained by associating to each element of a link to the following element. So each element size is lesser by 1 pointers than list. It is similar to list with the difference that unlike list it does not allow traverse backwards. Each element hold the reference to the next element but not the previous element. Each element having only single link, insertion and removal of element is more efficient than list. Forward list is more efficient than other containers like array, vector and deque in terms of insertion, deletion, moving and the algorithm like sort which use those operations.

    Unlike list, forward_list does not allow to access the elements directly. If you want to access to 7th elements you have to iterate from the beginning to the 7th element to access it. It is as efficient as a simple c-style singly-linked-list.

    Example of std::forward_list

    Code:
    #include<iostream>
    #include<forward_list>
    using namespace std;
    int main()
    {
        //Creating a forward_list container with braced initializer
        std::forward_list<int> flist{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
        auto cBeforeBeginItr = flist.cbefore_begin();
        cout << "Original list: ";
        while (++cBeforeBeginItr != flist.end())
        {
            cout << *cBeforeBeginItr << " ";
        }
        std::forward_list<int> myflist = flist;
        //Adding elements at the beginning
        myflist.emplace_front(0);
        //Revering the elements
        myflist.reverse();
        //Accessing the first element
        cout << "\n\nThe first element of final list:" << myflist.front() << endl;
        //Getting iterators
        auto cbeginItr = myflist.cbegin();
        auto cendItr = myflist.cend();
        
        //Accessing elements using iterator
        cout << "Final Elements: ";
        while (cbeginItr != cendItr)
        {
            std::cout << *cbeginItr << " ";
            ++cbeginItr;
        }
        std::cout << std::endl;
        return 0;
    }
    
    Output:
    Code:
    Original list: 1 2 3 4 5 6 7 8 9 10
    
    The first element of final list:10
    Final Elements: 10 9 8 7 6 5 4 3 2 1 0
    

    Set class (std::set)



    Header: <set>
    Declaration:
    Code:
    template < class T,                        // set::key_type/value_type
               class Compare = less<T>,        // set::key_compare/value_compare
               class Alloc = allocator<T>      // set::allocator_type
               > class set;
    
    Set is an associative container and store the unique elements in a specific order. Internally the elements are stored in a binary search tree. The value of an element also identifies itself, means the value is itself the key. The elements cannot be modified once they are in the container but they can be removed or inserted to the container. Set containers are slower than unordered_set to access individual elements by their key but it allows direct iteration on their elements based on their order. It supports bi-directional iterator.

    Example of std::set

    Code:
    #include<iostream>
    #include<set>
    using namespace std;
    int main()
    {
        //Creating a set container with braced initializer with default order
        std::set<int> originalset{ 1, 2, 30, 4, 15, 6, 7, 8, 90, 10 };
        auto myset = originalset;
        //Adding elements
        myset.emplace(0);
        myset.insert(40);
        myset.insert(13);
    
        auto endItr = originalset.end();
        auto beginItr = originalset.begin();
        cout << "Original list: ";
        while (beginItr != endItr)
        {
            cout << *beginItr << " ";
            beginItr++;
        }
        
        //Getting constant reverse iterators
        auto crbeginItr = myset.crbegin();
        auto crendItr = myset.crend();
        
        //Accessing elements using iterator
        cout << "\nFinal Elements in reverse order: ";
        while (crbeginItr !=crendItr )
        {
            std::cout << *crbeginItr << " ";
            ++crbeginItr;
        }
        std::cout << std::endl;
        if (myset.find(9) != myset.end())
            cout << "9 is present in the set" << endl;
        if (myset.find(10) != myset.end())
            cout << "10 is present in the set" << endl;
        return 0;
    }
    
    Output:
    Code:
    Original list: 1 2 4 6 7 8 10 15 30 90
    Final Elements in reverse order: 90 40 30 15 13 10 8 7 6 4 2 1 0
    10 is present in the set
    

    Unordered_set class (std::unordered_set)



    Header: <unordered_set>
    Declaration:
    Code:
    template < class Key,                        // unordered_set::key_type/value_type
               class Hash = hash<Key>,           // unordered_set::hasher
               class Pred = equal_to<Key>,       // unordered_set::key_equal
               class Alloc = allocator<Key>      // unordered_set::allocator_type
               > class unordered_set;
    unordered_set is an associative container and store the unique elements without any order. Internally the elements are stored in hash tables. The value of an element also identifies itself, means the value is itself the key. The elements cannot be modified once they are in the container but they can be removed or inserted in the container. unordered_set containers are faster than set to access individual elements by their key but slower in range iteration. It supports forward iterator.

    Example of std::unordered_set

    Code:
    #include<iostream>
    #include<unordered_set>
    using namespace std;
    int main()
    {
        //Creating an unordered_set container with braced initializer. Duplicate values are discarded
        std::unordered_set<int> originalset{ 1, 2,2, 30, 4, 15, 6, 7, 8, 90, 10 };
        auto myset = originalset;
        //Adding elements
        myset.emplace(0);
        myset.insert(40);
        myset.insert(13);
        //Rempving element
        myset.erase(1);
    
        auto endItr = originalset.end();
        auto beginItr = originalset.begin();
        cout << "Original list: ";
        while (beginItr != endItr)
        {
            cout << *beginItr << " ";
            beginItr++;
        }
        cout << "\nFinal list: ";
        unordered_set<int>::iterator itr = myset.begin();
        for (int i = 0;i < myset.size();++i)
        {
            cout << *itr << " ";
            ++itr;
        }
        std::cout << std::endl;
        if (myset.find(9) != myset.end())
            cout << "9 is present in the set" << endl;
        if (myset.find(10) != myset.end())
            cout << "10 is present in the set" << endl;
        return 0;
    }
    
    Output:
    Code:
    Original list: 1 90 2 6 30 4 7 15 8 10
    Final list: 90 2 6 30 4 7 15 8 10 0 40 13
    10 is present in the set
    

    Multiset class and unordered_multiset class


    (std::set & std::unordered_set)

    Header: <set> and <unordered_set>
    Declaration:
    Code:
    template < class T,                        // multiset::key_type/value_type
           class Compare = less<T>,        // multiset::key_compare/value_compare
           class Alloc = allocator<T> >    // multiset::allocator_type
           > class multiset;
    template < class Key,                         // unordered_multiset::key_type/value_type
             class Hash = hash<Key>,            // unordered_multiset::hasher
             class Pred = equal_to<Key>,        // unordered_multiset::key_equal
             class Alloc = allocator<Key>       // unordered_multiset::allocator_type
             > class unordered_multiset;
    Multiset and unordered_multiset are similar to set and unordered_set respectively with the property that they can contain duplicate values. These classes are also declared in the same headers <set> and <unordered_set>. For unordered multi-set, duplicate valued elements are stored in the same bucket

    Example of std::multiset and unordered_multiset

    Code:
    #include<iostream>
    #include<set>
    #include<unordered_set>
    using namespace std;
    int main()
    {
        //Creating an multiset container with braced initializer with duplicate values
        std::multiset<int> myoset{ 1, 2,2, 30, 4, 15, 6,2, 7, 8, 90, 10 };
        //Adding elements
        myoset.emplace(2);
        myoset.insert(15);
        myoset.insert(10);
        cout << "Ordered multiset:" << endl;
        for (int val : myoset)
            cout << val << " ";
        cout << endl << "The occurene of 2 in the set is " << myoset.count(2) << " times" << endl<<endl;
    
        //Creating an unordered_multiset container with braced initializer with duplicate values
        std::unordered_multiset<int> myuset{ 1, 2,2, 30, 4, 15, 6,2, 7, 8, 90, 10 };
        //Adding elements
        myuset.emplace(2);
        myuset.insert(15);
        myuset.insert(10);
        cout << "Unordered multiset:" << endl;
        for (int val : myuset)
            cout << val << " ";
        cout << endl << "The occurene of 15 in the set is " << myuset.count(15) << " times" << endl;
        return 0;
    }
    
    Output:
    Code:
    Ordered multiset:
    1 2 2 2 2 4 6 7 8 10 10 15 15 30 90
    The occurene of 2 in the set is 4 times
    
    Unordered multiset:
    1 2 2 2 2 6 30 4 7 15 15 8 90 10 10
    The occurene of 15 in the set is 2 times
    

    Maps:


    map, multimap, unordered_map and unordered_multimap (std::map, std::multimap, std::unordered_map and std::unordered_multimap)

    Header: <map> and <unordered_map>
    Declaration:
    Code:
    template < class Key,                                     // map::key_type
               class T,                                       // map::mapped_type
               class Compare = less<Key>,                     // map::key_compare
               class Alloc = allocator<pair<const Key,T> >    // map::allocator_type
               > class map;
    
    template < class Key,                                     // multimap::key_type
               class T,                                       // multimap::mapped_type
               class Compare = less<Key>,                     // multimap::key_compare
               class Alloc = allocator<pair<const Key,T> >    // multimap::allocator_type
               > class multimap;
    
    template < class Key,                                    // unordered_map::key_type
               class T,                                      // unordered_map::mapped_type
               class Hash = hash<Key>,                       // unordered_map::hasher
               class Pred = equal_to<Key>,                   // unordered_map::key_equal
               class Alloc = allocator< pair<const Key,T> >  // unordered_map::allocator_type
               > class unordered_map;
    
    template < class Key,                                    // unordered_multimap::key_type
               class T,                                      // unordered_multimap::mapped_type
               class Hash = hash<Key>,                       // unordered_multimap::hasher
               class Pred = equal_to<Key>,                   // unordered_multimap::key_equal
               class Alloc = allocator< pair<const Key,T> >  // unordered_multimap::allocator_type
               > class unordered_multimap;
    Maps are like set but the difference between sets and maps is that every element in the map is a key-value pair and the map elements are arranged and accessed on the basis of key and not the value. Key and value can be off different types. In case of sets value itself is treated as the key. Both sets and maps are implemented same way- binary search tree for ordered map and hash tables for unordered map.

    Example of map, multimap, unordered_map and unordered_multimap

    Code:
    #include<iostream>
    #include<map>
    #include<unordered_map>
    using namespace std;
    int main()
    {
        //Creating different types of map container with braced initializer
        std::map<int, string> mymap{ {1,"Cat"},{6,"Lion"},{5,"Tiger"},{3,"Panther"},{4,"Leopard"} };
        std::multimap<int, string> mymultimap{ { 1,"Cat" },{ 6,"Lion" },{ 5,"Tiger" },{ 3,"Panther" },{ 4,"Leopard" } };
        std::unordered_map<int, string> myumap{ { 1,"Cat" },{ 6,"Lion" },{ 5,"Tiger" },{ 3,"Panther" },{ 4,"Leopard" } };
        std::unordered_multimap<int, string> myumultimap{ { 1,"Cat" },{ 6,"Lion" },{ 5,"Tiger" },{ 3,"Panther" },{ 4,"Leopard" } };
        //Inserting elements
        mymap.emplace(2,"Big Cat");
        myumap.emplace(2, "Big Cat");
        mymultimap.emplace(2, "Big Cat");
        myumultimap.emplace(2, "Big Cat");
    
        //Inserting duplicate elements
        mymap.emplace(2, "Big Cat");
        myumap.emplace(2, "Big Cat");
        mymultimap.emplace(2, "Big Cat");
        myumultimap.emplace(2, "Big Cat");
    
        cout << "Ordered map:" << endl;
        for (pair<int,string> item : mymap)
            cout <<"\""<< item.second.c_str()<<"\"" << ", ";
        cout << endl << "The occurrence of Big Cat in the set is " << mymap.count(2) << " times" << endl<<endl;
    
        cout << "Ordered multimap:" << endl;
        for (pair<int, string> item : mymultimap)
            cout << "\"" << item.second.c_str() << "\"" << ", ";
        cout << endl << "The occurrence of Big Cat in the set is " << mymultimap.count(2) << " times" << endl << endl;
    
        cout << "Unordered map:" << endl;
        for (pair<int, string> item : myumap)
            cout << "\"" << item.second.c_str() << "\"" << ", ";
        cout << endl << "The occurrence of Big Cat in the set is " << myumap.count(2) << " times" << endl << endl;
    
        cout << "Unordered multimap:" << endl;
        for (pair<int, string> item : myumultimap)
            cout << "\"" << item.second.c_str() << "\"" << ", ";
        cout << endl << "The occurrence of Big Cat in the set is " << myumultimap.count(2) << " times" << endl << endl;
    
        return 0;
    }
    
    Output:
    Code:
    Ordered map:
    "Cat", "Big Cat", "Panther", "Leopard", "Tiger", "Lion",
    The occurrence of Big Cat in the set is 1 times
    
    Ordered multimap:
    "Cat", "Big Cat", "Big Cat", "Panther", "Leopard", "Tiger", "Lion",
    The occurrence of Big Cat in the set is 2 times
    
    Unordered map:
    "Cat", "Lion", "Tiger", "Panther", "Leopard", "Big Cat",
    The occurrence of Big Cat in the set is 1 times
    
    Unordered multimap:
    "Cat", "Lion", "Tiger", "Panther", "Leopard", "Big Cat", "Big Cat",
    The occurrence of Big Cat in the set is 2 times
    

    Stack class (std::stack)



    Header: <stack>
    Declaration: template <class T, class Container = deque<T> > class stack;

    Container adapter class stack is designed for the LIFO(last-in first-out) context where elements are inserted and removed only at and from one end. The element last inserted will be removed first. Inserting an element is called push operation and removing an element is called pop operation. This is a container adapter and use some other container to store the elements. The underlying container types should support following operations:
    • empty
    • size
    • back
    • push_back
    • pop_back
    vector, deque and list classes fulfills those requirement. Default container is deque. You can specify the container type while instantiation. Elements are inserted and removed from the back of the underlying container.

    Example of std::stack

    Code:
    #include<iostream>
    #include<stack>
    #include<vector>
    using namespace std;
    int main()
    {
        vector<int> v{1,2,3,4,5,6,7,8,9,10};
        //Stack initialize with vector object
        stack<int, vector<int>> mystack(v);
        cout << "Size of the initialized stack: " << mystack.size()<<endl;
        while (!mystack.empty())
        {
            cout << mystack.top() << " ";
            mystack.pop();
        }
        cout << endl;
        for (int i = 1;i < 6;++i)
        {
            mystack.emplace(i*i);  //emplace() is the better way than push() to insert an element
        }
        cout << "Size of the new stack: " << mystack.size() << endl;
        while (!mystack.empty())
        {
            cout << mystack.top() << " ";
            mystack.pop();
        }
        cout << endl;
        return 0;
    }
    
    Output:
    Code:
    Size of the initialized stack: 10
    10 9 8 7 6 5 4 3 2 1
    Size of the new stack: 5
    25 16 9 4 1
    

    Queue class (std::queue)



    Header: <queue>
    Declaration: template <class T, class Container = deque<T> > class queue;

    Container adapter class queue is designed for the FIFO(first-in first-out) context where elements are inserted at one end and removed from the other end. The element first inserted will be removed first and inserted last will be remove last. Inserting an element is called enque operation and removing an element is called dequeue operation. This is a container adapter and use some other container to store the elements. The underlying container types should support following operations:
    • empty
    • size
    • back
    • front
    • push_back
    • pop_front
    deque and list classes fulfills those requirement. Default container is deque. You can specify the container type while instantiation. Elements are inserted at the back of the container and remove from the front.

    Example of std::queue

    Code:
    #include<iostream>
    #include<queue>
    #include<list>
    using namespace std;
    int main()
    {
        list<int> lst{1,2,3,4,5,6,7,8,9,10};
        //Queue initialize with list object
        queue<int, list<int>> myqueue(lst);
        cout << "Size of the initialized queue: " << myqueue.size()<<endl;
        while (!myqueue.empty())
        {
            cout << myqueue.front() << " ";
            myqueue.pop();
        }
        cout << endl;
        for (int i = 1;i < 6;++i)
        {
            myqueue.emplace(i*i);  //emplace() is the better way than push() to insert an element
        }
        cout << "Size of the new queue: " << myqueue.size() << endl;
        while (!myqueue.empty())
        {
            cout << myqueue.front() << " ";
            myqueue.pop();
        }
        cout << endl;
        return 0;
    }
    
    Output:
    Code:
    Size of the initialized queue: 10
    1 2 3 4 5 6 7 8 9 10
    Size of the new queue: 5
    1 4 9 16 25
    

    Priority_queue class (std::priority_queue)



    Header: <queue>
    Declaration:
    Code:
    template <class T, class Container = vector<T>,
      class Compare = less<typename Container::value_type> > class priority_queue;
    
    Container adapter class priority_queue is designed such a way that it’s greatest element is always the first element according to a strict weak ordering criterion. Internally it maintains a heap structure where an element can be inserted at any moment and only the max heap element can be retrieved which is at the top of the priority_queue. This is a container adapter and use some other container to store the elements. The underlying container types should support following operations:
    • empty
    • size
    • front
    • push_back
    • pop_back
    deque and vector classes fulfills those requirement. Default container is vector. You can specify the container type while instantiation. Elements are popped from the back of the specific container. Support of random access iterator is required to keep a heap structure internally all the time. This is done by the container adapter by automatically calling algorithm functions make_heap, push_heap and pop_heap when needed.

    Example of std::priority_queue

    Code:
    #include<iostream>
    #include<queue>
    #include<functional>
    using namespace std;
    int main()
    {
        deque<int> dq{1,10,3,4,6,5,7,8,9,2};
        //Priority que will keep the smallest number at the top
        priority_queue<int, deque<int>, greater<int>> mypqueue(greater<int>(), dq);
        cout << "Size of the initialized priority queue: " << mypqueue.size()<<endl;
        while (!mypqueue.empty())
        {
            cout << mypqueue.top() << " ";
            mypqueue.pop();
        }
        cout << endl;
        for (int i = 1;i < 6;++i)
        {
            mypqueue.emplace(i*10);  //emplace() is the better way than push() to insert an element
        }
        cout << "Size of the new priority queue: " << mypqueue.size() << endl;
        while (!mypqueue.empty())
        {
            cout << mypqueue.top() << " ";
            mypqueue.pop();
        }
        cout << endl;
        return 0;
    }
    
    Output:
    Code:
    Size of the initialized priority queue: 10
    1 2 3 4 5 6 7 8 9 10
    Size of the new priority queue: 5
    10 20 30 40 50
    

    Common Functions



    STL containers are not only generic in terms of type of elements but also in terms of functionality. There are lot of functionality and members are common across the containers. Here are major examples:
    1. All sequence containers support uniform initialization and assignment operator=().
    2. Containers like vector, array, deque, and map support element access operator [] and function at() which take the index or a key value and return the element.
    3. All the containers support begin(), end(), cbegin() and cend() member functions which return random access(for array, vector, deque), bidirectional(for list and ordered associative containers) or forward iterators (for forward_list and unordered associative containers) or the constant version of those iterators
    4. Containers except forward_list and unordered associative containers support rbegin(), rend(), crbegin() and crend() which return random access (for array, vector, deque) and bidirectional (list and ordered associative containers) reverse iterators or constant versions of those iterators.
    5. All the containers except the forward_list support size() member function which returns the number of elements in a container.
    6. All containers support max_size() member function which return the number of maximum elements a container can hold.
    7. All sequence containers except array support resize() member function which re-size the container so that it can hold a given number of elements.
    8. All the containers support member function empty() which returns true if the container is empty, else return false.
    9. All containers except array and forward_list, support emplace() (or emplace_after() ), insert( or insert_after() ) and erase( or erase_after() ) member functions which insert a new element or remove an existing element at the given position specified by the given iterator.
    10. All containers except array support the clear() member function which remove all the elements and make the size of the container to 0.
    11. All containers support swap() member function which replaces its elements with the elements of another given container of same type.
    12. All sequence containers except array and forward_list support emplace_back(), push_back(), and pop_back() functions to insert a new element at the end of the container or remove the first element.
    13. Sequence container except array and vectors support emplace_front(), push_front() and pop_front() functions to insert a new element at the front or remove the first element.
     

Share This Page