#include <deque>
#include <set>
#include <map>
#include <string>
#include <stack>
#include <queue>

using namespace std;

void sequence_containers()
{
    // vector
    {
        vector<int> vec;
        for (int i=0;i<10;++i)
            vec.push_back(i);
        for (auto & e : vec)
            cout << e << " ";
        cout << "\n";
    }
    
    // deque
    {
        deque<int> deq; // #include <deque>
        for (int i=0;i<10;++i)
        {
            deq.push_back(i);
            deq.push_front(i);
        }
        for (auto & e : deq)
            cout << e << " ";
        cout << "\n";
    }
}

void associative_containers()
{
    //set // 원소가 중복이 되지 않는다.
    {
        set<string> str_set;
        
        str_set.insert("Hello");
        str_set.insert("World");
        str_set.insert("Hello");
        
        cout << str_set.size() << "\n"; // size = 2
        
        for (auto & e : str_set)
            cout << e << " ";
        cout << "\n";
    }
    
    //multiset : duplication is allowed
    {
        std::multiset<string> str_set;
        
        str_set.insert("Hello");
        str_set.insert("World");
        str_set.insert("Hello");
        
        cout << str_set.size() << "\n"; // size = 3
        
        for (auto & e : str_set)
            cout << e << " ";
        cout << "\n";
    }
    
    // map : key/value
    {
        std::map<char, int> map;
        map['a'] = 10;
        map['b'] = 20;
        map['c'] = 50;
        
        cout << map['a'] << "\n";
        
        map['a'] = 100;
        
        cout << map['a'] << "\n";
        
        for (auto & e : map)
            cout << e.first << " " << e.second << " ";
        cout << "\n";
    }
    
    //multimap : duplicated keys
    {
        std::multimap<char, int> map;
        map.insert(std::pair('a', 10)); // Before c++ 14, pair<char, int>('a',10)
        map.insert(std::pair('b', 10));
        map.insert(std::pair('a', 100));
        
        cout << map.count('a') << "\n";
        
        for (auto & e : map)
            cout << e.first << " " << e.second <<  " ";
        cout << "\n";
    }
}

void container_adapters();
{
    //stack
    {
        cout << "Stack" << "\n";
        
        std::stack<int> stack;
        stack.push(1); // push adds a copy
        stack.emplace(2); // emplace constructs a new object
        stack.emplace(3);
        cout << stack.top() << "\n"; // 3
        stack.pop();
        cout << stack.top() << "\n"; // 2
    }
    
    // queue
    {
        cout << "Queue" << "\n";
        
        std::queue<int> queue;
        queue.push(1);
        queue.push(2);
        queue.push(3);
        cout << queue.front() << " " << queue.back() << "\n"; // 1 3
        queue.pop();
        cout << queue.front() << " " << queue.back() << "\n"; // 2 3
    }
    
    //priority queue
    {
        cout << "Priority queue" << "\n";
        std::priority_queue<int> queue;
        for (const int n : {1,8,5,6,3,4,0,9,7,2})
            queue.push(n);
       	for (int i=0;i<10;++i)
        {
            cout << queue.top() << "\n"; // 9 8 7 ... 0
            queue.pop();
        }
    }
}

int main()
{
    sequence_containers();
    
    associative_containers();
    
    container_adapters();
    
    return 0;
}