Introduction and use of stack
- stack is a container adapter, which is specially used in the context of last in first out operation. Its deletion can only insert and extract elements from one end of the container.
- Stack is implemented as a container adapter. A container adapter encapsulates a specific class as its underlying container, and provides a set of specific member functions to access its elements. With a specific class as its underlying element, the tail of a specific container (i.e. the top of the stack) is pushed in and popped out.
- The underlying container of stack can be any standard container class template or some other specific container classes. These container classes should support the following operations:
- Empty: empty judgment
- back: get tail element operation
- push_back: tail insert element operation
- pop_back: delete element at the end
- The standard containers vector, deque and list meet these requirements. By default, if no specific underlying container is specified for stack, deque is used by default.
Note: stack and queue are adapters (adapters), which are realized by conversion, not directly. They are realized by packaging other containers
Use of stack
void test_stack() { stack<int> st; st.push(1); st.push(2); st.push(3); st.push(4); cout << st.size() << endl; while (!st.empty()) { cout << st.top() << " "; st.pop(); } cout << endl; cout << st.size() << endl; }
Simulation of stack
#pragma once #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<deque> #include<vector> #include<list> using namespace std; namespace lc { template<class T,class Container=deque<T>> //stack is a container adaptation (package conversion) class stack { public: void push(const T& x) { _con.push_back(x); } void pop() { _con.pop_back(); } const T& top() { return _con.back(); } size_t size() { return _con.size(); } bool empty() { return _con.empty(); } private: Container _con; }; }
Introduction and use of queue
- A queue is a container adapter designed to operate in a FIFO context (first in first out), where elements are inserted from one end of the container and extracted from the other end.
- Queue is implemented as a container adapter, which encapsulates a specific container class as its underlying container class, and queue provides a set of specific member functions to access its elements. Elements enter the queue from the end of the queue and exit the queue from the head of the queue.
- The underlying container can be one of the standard container class templates or other specially designed container classes. The bottom container shall at least support the following operations:
- Empty: check whether the queue is empty
- size: returns the number of valid elements in the queue
- front: returns the reference of the queue head element
- back: returns a reference to the end of the queue element
- push_back: enter the queue at the end of the queue
- pop_front: exit the queue at the head of the queue
- The standard container classes deque and list meet these requirements. By default, if no container class is specified for queue instantiation, the standard container deque is used.
Use of queue
void test_queue() { queue<int> q; q.push(1); q.push(2); q.push(3); q.push(4); cout << q.size() << endl; while (!q.empty()) { cout << q.front() << " "; q.pop(); } cout << endl; cout << q.size() << endl; }
Simulation Implementation of queue
#pragma once #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<deque> #include<vector> #include<list> using namespace std; namespace lc { template<class T, class Container = deque<T>> //queue is a container adapted (encapsulated and converted) class queue { public: void push(const T& x) { _con.push_back(x); } void pop() { _con.pop_front(); } const T& front() { return _con.front(); } const T& back() { return _con.back(); } size_t size() { return _con.size(); } bool empty() { return _con.empty(); } private: Container _con; }; }
Container Adapters
Adapter is a design pattern (design pattern is a set of repeatedly used, known by most people, classified and catalogued, and the summary of code design experience). This pattern is to convert the interface of one class into another interface desired by customers.
Note: Although elements can also be stored in stack and queue, they are not divided into the ranks of containers in STL, but called container adapters. This is because stack and queue only wrap the interfaces of other containers. Stack and queue in STL use deque by default
Supplement:
vector (continuous physical space):
advantage:
- Random access
- High CPU cache hit rate
Disadvantages:
- The space is not enough and needs to be increased. The cost of capacity increase is high, and there is still a certain waste of space
- Head and middle insertion and deletion, low efficiency O(N)
list:
advantage:
- Apply for space on demand to free up space
- Inserting and deleting data anywhere is O(1) efficient
Disadvantages:
- Random access is not supported
- Low CPU cache hit rate
Advantages and disadvantages of deque:
- Double ended queue indicates that it is very suitable for head plug deletion, tail plug deletion and tail deletion. It is very suitable to be the default adaptation container of stack and queue
- Inserting and deleting data in the middle of the double ended queue is cumbersome and inefficient (1. Move the overall data, 2. Move the current buff data - record the size of each buff array, and the size of each buff array is inconsistent)
- deque is a compromise design, which is not perfect. The efficiency of random access is less than that of vector, and the insertion and deletion at any position is less than that of list
- A pile of data should be sorted with vector, inserted and deleted at any position with list, inserted and deleted at the beginning and end with multi-purpose deque
Note: combining the advantages and disadvantages of list and vector, the data structure deque combining central control array (pointer array) and fixed length buff array can be improved and designed