【C++】第七章:STL之stack&&queue的模拟实现

本文详细介绍了C++ STL中stack和queue的基本定义、使用方法,包括容器适配器的概念,以及deque为何适合做底层数据结构的解释。还展示了如何模拟实现stack和queue,以及适配器在选择底层容器中的作用。
摘要由CSDN通过智能技术生成

stack&&queue的使用

stack的定义

方式一: 使用默认的适配器定义栈。

stack<int> stk;

方式二: 使用特定的适配器定义栈。

stack<int, vector<int>> stk;
stack<int, list<int>> stk;

注意:如果没有指定适配器,默认使用deque

stack的使用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qmXCE2PU-1631182066448)(D:\github\gitee\bolgs\【C++】第七章STL之stack&&queue的模拟实现.assets\1631181644346.png)]

#include <iostream>
#include <stack>
using namespace std;

int main()
{
	stack<int> st;
	st.push(1);
	st.push(2);
	st.push(3);
	st.push(4);
	cout << st.size() << endl; //4
	while (!st.empty())
	{
		cout << st.top() << " ";
		st.pop();
	}
	cout << endl; //4 3 2 1
	return 0;
}

queue的定义

方式一: 使用默认的适配器定义队列。

queue<int> q;

方式二: 使用特定的适配器定义队列。

queue<int, vector<int>> q;
queue<int, list<int>> q;

注意:如果没有指定适配器,默认使用deque

queue的使用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DngX8cWt-1631182066450)(D:\github\gitee\bolgs\【C++】第七章STL之stack&&queue的模拟实现.assets\1631181667674.png)]

#include <iostream>
#include <queue>
using namespace std;

int main()
{
	queue<int> q;
	q.push(1);
	q.push(2);
	q.push(3);
	q.push(4);
	cout << q.size() << endl; // 4
	while (!q.empty())
	{
		cout << q.front() << " ";
		q.pop();
	}
	cout << endl; //1 2 3 4
	return 0;
}

stack&&queue的模拟实现

一、容器适配器

1.什么是适配器

适配器是一种设计模式,该种模式是将一个类的接口转换成客户希望的另外一个接口。 而容器适配器就是通过底层封装一个容器来实现另一个容器的功能展示。

在STL中像stackqueuepriority_queue都是容器的适配器。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-98uWJL5r-1632015661211)(D:\github\gitee\bolgs\【C++】第七章STL之stack&&queue的模拟实现.assets\1632014287324.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PVhgOQQs-1632015661213)(D:\github\gitee\bolgs\【C++】第七章STL之stack&&queue的模拟实现.assets\1632014276544.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yS5NhbjE-1632015661214)(D:\github\gitee\bolgs\【C++】第七章STL之stack&&queue的模拟实现.assets\1632014305971.png)]

在默认情况下,stackqueue都是使用deque作为底层的数据结构,priority_queue使用vector作为底层的数据结构。

2.容器适配器如何选择底层数据结构?

我们这里就介绍一下deque为何可以作为stackqueue的底层数据结构。

deque(双端队列):是一种双开口的"连续"空间的数据结构,双开口的含义是:可以在头尾两端进行插入和删除操作,且时间复杂度为O(1)。而且可以使用[]随机访问任意元素。与vector比较,头插效率高,不需要搬移元素;与list比较,空间利用率比较高。

deque既可以随机访问元素,又可以随机的掺入删除元素,看似很棒的一个容器,但是平常却很少使用。

deque的缺点:

  • 因为deque的底层实现非常的复杂,所以导致[]访问元素的时候,不如vector计算的快。
  • 在任意位置插入元素的时候,不如list快。
  • 所以在大量访问元素的时候,仍然使用vector,在大量插入元素的时候,仍然使用list
  • 因为底层的实现,所以deque迭起起访问效率不高。

deque的优点:

  • deque在头尾两端的插入删除元素的效率还是很高的,这样就可以弥补vector在头部位置操作的效率,并且deque在扩容的时候,代价要比vector小的多。
  • 而相比list,因为deque的底层是连续的,所以deque空间利用率比较高,空间碎片化小,缓存利用率高。

由于deque在头尾部的操作效率比较高,而stackqueue都是线性的数据结构,功能基本上都是对于头尾部的操作,并且stackqueue都没有迭代器访问,所以使用deque就是最好的选择了。

二、模拟实现

stackqueue都叫做容器的适配器,简单的来说就是,这个容器就是另一个容器的一个子集。通过封装了一个功能比较强大的容器,并只体现出这个封装容器的部分功能,从而得到了另一个容器,这就出现了容器的适配器。

如果没有指定适配器,stackqueue的底层默认使用deque作为封装的容器。

#include <iostream>
#include <deque>
using namespace std;

namespace mystack {
    
    template<class T, class Container = deque<T>>
    class stack {
    public:
        stack() {

        }

        void push(const T& val) {
            _container.push_back(val);
        }

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

        T& top() {
            return _container.back();
        }
        // 注意这里必须要这个接口
        // 因为const对象返回的top()是不可以被修改的
        const T& top() const {
            return _container.back();
        }

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


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

    private:
        Container _container;
    };


}


namespace myqueue
{
    template<class T, class Container = deque<T>>
    class queue {
    public:
        queue() {}

        void push(const T& val) {
            _container.push_back(val);
        }

        void pop() {
            _container.pop_front();
        }

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

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

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

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

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

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

    private:
        Container _container;      
    };

    void test() {
        queue<int> q;
        q.push(1);
        q.push(2);
        while (!q.empty()) {
            cout << q.front();
            q.pop();
        }
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hyzhang_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值