基于STL的自定义栈与队列实现:灵活选择底层容器的模板设计

文章目录

前言:

在本文中,我们将分析一个模拟C++标准模板库(STL)栈的自定义实现以及模仿C++标准模板库(STL)队列的自定义实现。该stack类模板允许在底层容器的选择上具有灵活性、该queue类模板采用灵活的容器选择机制,默认使用std::deque作为底层容器,这与STL设计相似。接下来,我们将深入研究代码的结构、功能,以及使用模板和容器组合在C++中实现的优势。

代码

这是在Stack命名空间下的主要类定义:

cpp 复制代码
namespace Stack
{
    template<class T, class Container>
    class stack
    {
    public:
        void push(const T& x) { _con.push_back(x); }
        void pop() { _con.pop_back(); }
        const T& top() const { return _con.back(); }
        size_t size() const { return _con.size(); }
        bool empty() const { return _con.empty(); }
    
    private:
        Container _con;
    };
}

模板设计

该类是一个模板,接受两个参数:

T:存储在栈中的元素类型。

Container:底层容器类型,用于管理栈元素的存储。

这种设计使我们能够自定义底层的存储容器,允许使用std::vector、std::list或std::deque作为底层数据结构。在标准库中,std::stack默认使用std::deque作为底层容器,因为它在两端插入和移除元素时的效率较高。

主要成员函数

让我们逐一了解主要的成员函数:

push(const T& x):用于将一个元素x压入栈顶。此实现使用了push_back函数,因为无论使用哪种容器,我们都希望在容器末尾添加新元素。

pop():用于移除栈顶元素。与push类似,此处使用pop_back,因为需要从容器的末尾移除元素。

top() const:返回栈顶元素的常量引用。这是只读访问,因为栈顶元素不能通过top()修改。

size() const:返回栈中的元素数量,直接调用容器的size()函数。

empty() const:用于检查栈是否为空,直接调用容器的empty()函数。

底层容器的选择

在这个实现中,底层容器的选择灵活。例如:
std::vector :可以用于存储连续内存中的栈,但当栈中的元素较多时,可能会带来内存的重新分配开销。
std::list :是链式存储结构,不支持随机访问,但在频繁插入和删除操作时性能较优。
std::deque :是双端队列,既支持随机访问,又可以在两端进行高效的插入和删除操作,是STL中std::stack的默认容器。

小结

该stack模板类通过组合不同的容器类型实现了灵活的栈结构,符合STL设计原则。在实际使用中,根据需求选择合适的底层容器,可以进一步优化栈的性能。

这是在Queue命名空间下的queue类定义:

cpp 复制代码
namespace Queue
{
    template<class T, class Container = std::deque<T>>
    class queue
    {
    public:
        void push(const T& x) { _con.push_back(x); }
        void pop() { _con.pop_front(); }
        const T& front() const { return _con.front(); }
        const T& back() const { return _con.back(); }
        size_t size() const { return _con.size(); }
        bool empty() const { return _con.empty(); }
    
    private:
        Container _con;
    };
}

模板设计

该类是一个模板,接受两个参数:

T:存储在队列中的元素类型。

Container:底层容器类型,用于存储队列元素,默认使用std::deque。

这种设计允许我们在实现队列时选择不同的容器,如std::deque、std::vector或std::list。然而,std::deque是STL中默认的底层容器,因其支持在两端快速插入和删除元素,非常适合队列的FIFO(First In, First Out)特性。

主要成员函数解析
以下是queue类中的核心成员函数:

void push(const T& x)

push函数将元素x添加到队列末尾。此函数调用_con.push_back(x),无论底层容器是什么类型,都确保新元素添加到队列的"尾部"。

void pop()

pop函数移除队列的第一个元素。它调用_con.pop_front(),遵循队列的FIFO特性,将队首元素出队。这种操作在std::deque和std::list中效率较高,而在std::vector中效率相对较低。

const T& front() const

front函数返回队列首元素的常量引用。由于是常量引用,用户可以读取但不能修改队首元素。

const T& back() const

back函数返回队列尾元素的常量引用。用户可以读取队列中的最后一个元素,但不能通过此方法修改它。

size_t size() const

size函数返回队列中元素的数量,直接调用底层容器的size()函数。

bool empty() const

empty函数检查队列是否为空,直接调用底层容器的empty()函数。

底层容器的选择

在该实现中,可以选择不同的容器作为底层数据结构,以下是常见的选择及其特点:
std::deque :STL中std::queue的默认容器。支持两端快速插入和删除,非常适合队列的特性。
std::list :链表结构,允许在两端常数时间内插入和删除元素,适用于需要频繁插入和删除的场景。
std::vector:虽然可以作为底层容器,但由于在队首插入和删除元素效率较低,通常不推荐在队列中使用。

关于stack的示例代码

cpp 复制代码
#include "stack.h"
#include <vector>
#include <list>
#include <iostream>

int main() {
    // 使用 std::vector 作为底层容器的栈
    bit::stack<int, std::vector<int>> vector_stack;
    vector_stack.push(10);
    vector_stack.push(20);
    vector_stack.push(30);
    vector_stack.pop();  // 移除栈顶元素
    std::cout << "Top element in vector-based stack: " << vector_stack.top() << std::endl;  // 输出栈顶元素
    std::cout << "Stack size: " << vector_stack.size() << std::endl;  // 输出栈的大小

    // 使用 std::list 作为底层容器的栈
    bit::stack<int, std::list<int>> list_stack;
    list_stack.push(40);
    list_stack.push(50);
    list_stack.push(60);
    list_stack.pop();  // 移除栈顶元素
    std::cout << "Top element in list-based stack: " << list_stack.top() << std::endl;  // 输出栈顶元素
    std::cout << "Stack size: " << list_stack.size() << std::endl;  // 输出栈的大小

    return 0;
}

关于queue的示例代码

cpp 复制代码
#include "queue.h"
#include <deque>
#include <list>
#include <vector>
#include <iostream>

int main() {
    bit::queue<int, std::deque<int>> deque_queue;
    deque_queue.push(10);
    deque_queue.push(20);
    deque_queue.push(30);
    deque_queue.pop();
    std::cout << "Front element in deque-based queue: " << deque_queue.front() << std::endl;

    bit::queue<int, std::list<int>> list_queue;
    list_queue.push(40);
    list_queue.push(50);
    list_queue.push(60);
    list_queue.pop();
    std::cout << "Front element in list-based queue: " << list_queue.front() << std::endl;

    return 0;
}
相关推荐
‘’林花谢了春红‘’3 小时前
C++ list (链表)容器
c++·链表·list
机器视觉知识推荐、就业指导5 小时前
C++设计模式:建造者模式(Builder) 房屋建造案例
c++
Yang.997 小时前
基于Windows系统用C++做一个点名工具
c++·windows·sql·visual studio code·sqlite3
熬夜学编程的小王7 小时前
【初阶数据结构篇】双向链表的实现(赋源码)
数据结构·c++·链表·双向链表
zz40_7 小时前
C++自己写类 和 运算符重载函数
c++
六月的翅膀7 小时前
C++:实例访问静态成员函数和类访问静态成员函数有什么区别
开发语言·c++
liujjjiyun8 小时前
小R的随机播放顺序
数据结构·c++·算法
¥ 多多¥8 小时前
c++中mystring运算符重载
开发语言·c++·算法
天若有情6739 小时前
c++框架设计展示---提高开发效率!
java·c++·算法