STL container: dual end queue deque and priority queue priority_queue

Posted by chadtimothy23 on Fri, 18 Feb 2022 12:12:55 +0100

Double ended queue deque

deque is a double ended queue, which can be inserted at the head and tail, or deleted at the head and tail. Its advantage is that it combines the advantages of vector and list, but realizes random access and header plug deletion. When the space is not enough and needs to be expanded, it does not need to be as complex as vector. It only needs to add a new space on the basis of the original space.

Although deque has the advantages of vector and list, due to its complex structure, some operation efficiency is very low. For example, sorting directly in deque is even better than copying the data to vector first, sorting in vector and then copying back to deque.

The bottom space of deque can be said to be continuous, but not absolutely continuous. Deque is implemented by controlling multiple arrays. There is a map table inside, and each item is a pointer that only wants a continuous physical space (buffer). The data is placed in that continuous space.

  • Whenever you need to access elements, first find the specific storage space through the map. Then access through the pointer. Although it is not accessed directly through the pointer, the access efficiency is much higher than that of the list.
  • When header insertion is required, find the first valid element of the map. If there is space left for the pointer, insert it directly. If there is no space, dynamically open up a space and place the pointer in front of the first valid element of the map. Then store the elements in the last position of the newly opened space. There is no need to move elements. As efficient as list. If the map is full, re open the space and copy the original map to the new map.

The iterator of deque consists of four parts, pointing to the first position of the current buffer, and pointing to the last position of the current buffer. Point to the current element cur, and node saves the location of the buffer in the map. First and last are used as the boundary of the buffer to prevent cross-border. Node can jump to the next or previous buffer.

Stack based on deque

Stack is a first in and last out data structure, that is, it can only be inserted and deleted at one end. Deque can be inserted and deleted in both directions. So we can implement a stack by encapsulating deque again. The stack of STL standard library is implemented based on deque.

There are not many interfaces in the stack. The following is a simulated stack.

template<class T, class Con = deque<T>>
class stack
{
public:
	stack() {}
	void push(const T& x) {
		_c.push_back(x);
	}

	void pop() {
		_c.pop_back();
	}

	T& top() {
		return _c.back();
	}

	const T& top()const {
		return _c.back();
	}

	size_t size()const {
		return _c.size();
	}

	bool empty()const {
		return _c.empty();
	}

private:
	Con _c;
};

Encapsulate the interface of deque and only expose some usable interfaces to form a stack.

deque based queue

Similarly, a queue is a first in first out data structure. In the same way, we can encapsulate deque into a queue.

template<class T, class Con = deque<T>>
class queue
{
public:
	queue() {};

	void push(const T& x) {
		_c.push_back();
	}

	void pop() {
		_c.pop();
	}

	T& back() {
		return _c.back();
	}

	const T& back()const {
		return _c.back();
	}

	T& front() {
		return _c.front();
	}

	const T& front()const {
		return _c.front();
	}

	size_t size()const {
		return _c.size();
	}

	bool empty()const {
		return _c.empty();
	}
private:
	Con _c;
};

Priority queue priority_queue

Priority queue means that the elements in the queue have weights. Whenever an element enters the queue, it will reorder the queue elements according to the weights, which can be simply understood as building a heap.

Use priority queue to build a large root heap by default.

#include <queue>
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
// test priority queue...
	int ia[9] = {0,1,2,3,4,8,9,3,5};
	priority_queue<int> ipq(ia, ia+9);
	cout << "size=" << ipq.size() << endl; // size=9
	for(int i=0; i<ipq.size(); ++i)
		cout << ipq.top() << ' '; // 9 9 9 9 9 9 9 9 9
	cout << endl;
	while(!ipq.empty()) {
		cout << ipq.top() << ' '; // 9 8 5 4 3 3 2 1 0
		ipq.pop();
	}
	cout << endl;
	return 0;
}

To build a small root heap, you need to specify parameters and the underlying container.

#include <queue>
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
	// test priority queue...
	int ia[9] = { 0,1,2,3,4,8,9,3,5 };
	priority_queue<int, vector<int>, greater<int>> ipq(ia, ia + 9);
	cout << "size=" << ipq.size() << endl; // size=9
	for (int i = 0; i < ipq.size(); ++i)
		cout << ipq.top() << ' '; // 0 0 0 0 0 0 0 0 0
	cout << endl;
	while (!ipq.empty()) {
		cout << ipq.top() << ' '; // 0 1 2 3 3 4 5 8 9
		ipq.pop();
	}
	cout << endl;
	return 0;
}

Topics: C++ data structure queue pointer STL