栈、队列和堆详解(c++)

本文详细介绍了C++中栈、队列、堆的实现原理和使用,包括stack、queue和priority_queue的相关成员函数,以及deque的组织形式、插入和删除元素的操作。文章还探讨了为何在实现栈时选择deque而非vector,以及队列默认使用deque的原因。最后,简要提及了容器和容器适配器的概念。
摘要由CSDN通过智能技术生成

我们先模拟实现, 然后根据代码讲解如何使用.

目录

一.栈

1.stack类中的相关成员

2.stack成员函数的具体实现

3.stack的使用

 二.队列

1.queue类中的相关成员

2.queue成员函数的具体实现

3.queue的使用

三.堆

1.priority_queue的特性介绍

2.priority_queue类中的相关成员

3.priority_queue类中成员函数的具体实现

四.deque的介绍

1.deque的组织形式

2.deque插入元素

3.deque删除元素

4.deque缺陷

五.容器和容器适配器

1.容器

2.适配器


一.栈

因为c++编译器中已经给出了stack, 所以我们在实现时把其放到自己的命名空间中.

1.stack类中的相关成员

采用模板类的方式实现, 可以针对于各种不同的数据, 因为c++中已经给出了很多可以用来实现stack的容器, 我们这里选用deque(双端队列).(deque在后面会详细讲解)

功能介绍:

①.push入栈.

②.pop出栈.

③.top访问栈顶元素.

④.size计算栈中元素个数.

⑤.empty判断栈中是否为空.

为什么使用deque而不是vector实现栈?

1.首先我们要知道, 我们实现的栈只有两种操作, 一种是push, 一种是pop, 也就是出栈和入栈两种操作, 因此使用vector, list, deque 都可以, 但他们的性能上有区别, 所以我们在使用的时候, 需要根据实际情况来选择使用那种容器, 但这里为什么将deque作为stack的默认容器呢? 我们平时在c中实现的satck都是使用动态数组来完成的, 也就是vector那么为什么在这里就不使用了, 其实它是考虑了扩容的问题, 因为我们使用vector, 一但容器容量满了, 就需要扩容, 但vector扩容时十分耗费资源, 需要重新申请空间和拷贝元素, 而如果我们使用deque的话, 实现push和pop两个操作和vector相似, 并且扩容时相对比较方便, 因此在这里编译器选择使用deque来作为stack的默认容器.  

2.栈不需要遍历, 因此刚好把deque的劣势规避了, 所以使用deque更加合适.

    template<class T, class Con = deque<T>>

    class stack{

    public:

        stack();

        void push(const T& x) ;

        void pop() ;

        T& top() ;

        const T& top()const ;

        size_t size()const ;

        bool empty()const ;

    private:

        Con _c;

    };

2.stack成员函数的具体实现

a.构造函数不需要显示定义, 默认的构造函数会调用deque的构造函数对类的数据成员进行初始化.

b.push入栈

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

直接调用deque的push_back函数, 向双端队列尾部插入元素即可.

c.pop出栈

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

同理, 调用deque的pop_back函数, 从双端队列尾部删除元素即可.

d.top访问栈顶元素

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

返回双端队列的尾部元素.(const类型的top与普通top完全相同)

e.size有效元素个数

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

依然是返回双端队列中的有效元素个数, 调用deque的size函数.

f.empty判空

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

调用deque的empty函数, 判断双端队列中元素是否为空.

3.stack的使用

测试:

①.创建栈.

②.向栈中插入元素.

③.打印栈顶元素.

④.打印栈中元素个数.

⑤.出栈.

⑥.打印栈顶元素.

⑦.打印栈中元素个数.

    lz::stack<int> s1;
    s1.push(1);
    s1.push(2);
    s1.push(3);
    s1.push(4);
    s1.push(5);
    s1.push(6);
    cout << s1.top() << endl;
    if (!s1.empty()) {
        cout << s1.size() << endl;
    }
    s1.pop();
    s1.pop();
    s1.pop();
    cout << s1.top() << endl;
    if (!s1.empty()) {
        cout << s1.size() << endl;
    }

运行结果:

 二.队列

同样我们的队列需要在自己的命名空间中实现.

1.queue类中的相关成员

采用模板类的方式实现, 应对于不同类型的数据, 底层使用的默认容器为deque.

功能介绍:

①.push入队列.

②.pop出队列.

③.back访问队列尾部元素.

④.front访问队列首部元素.

⑤.size返回队列中有效元素个数.

⑥.empty判断队列是否为空.

为什么默认容器使用deque而不使用list?

1.queue不需要存储一些额外的内容, 而list中的每个结点还存储了next | prev两个结构体指针, 所以使用list会浪费内存空间.

2.deque是分段连续的, 因此其缓存效率高.

3.queue不需要遍历, 因此规避了deque的劣势.

    template<class T, class Con = deque<T>>

    class queue{

    public:

        queue() ;

        void push(const T&a
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

陆陆陆ovo

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

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

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

打赏作者

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

抵扣说明:

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

余额充值