【C++练级之路】【Lv.9】【STL】stack类和queue类的模拟实现

简介: 【C++练级之路】【Lv.9】【STL】stack类和queue类的模拟实现

一、容器适配器

STL并没有将stack和queue划分为容器,而是将其称为容器适配器,原因是stack和queue只是对其他容器的接口进行了封装。

这也让stack和queue模拟实现起来异常简单,所以两个合在一起讲解介绍。

二、stack

细节:

  1. stack具有LIFO(后进先出)性质
  2. 默认容器使用vector,使用尾插尾删效率高(STL库中使用deque)
template<class T, class Container = vector<T>>
class stack
{
public:
private:
  Container _con;
};

2.1 push

压栈

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

2.2 pop

出栈

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

2.3 top

获取栈顶元素

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

2.4 size

获取栈的有效元素个数

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

2.5 empty

判断栈是否为空

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

三、queue

细节:

  1. queue具有FIFO(先进先出)性质
  2. 默认容器使用list,使用尾插头删效率高(STL库中使用deque)
template<class T, class Container = list<T>>
class queue
{
public:
private:
  Container _con;
};

3.1 push

入队

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

3.2 pop

出队

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

3.3 front

获取队头元素

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

3.4 back

获取队尾元素

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

3.5 size

获取队列的有效元素个数

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

3.6 empty

判断队列是否为空

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

四、deque

4.1 deque的介绍

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

4.2 deque的底层结构

其实,deque并不是一整块连续空间,而是一段一段连续的小空间结合在一起。deque有一个中控数组,存放一段段小空间的指针,类似动态开辟的二维数组。

一开始在中间开辟空间,随后根据需求向两边进行扩容。

所以,针对分段连续的空间结构,为了支持随机访问,设计出了比较复杂的迭代器。

这样的空间结构,也导致遍历的效率变得十分低下,因为deque的迭代器需要频繁判断是否抵达分段空间的边界

4.3 deque的优势与缺陷

优势:

  • 支持随机访问
  • 头尾的插入删除,时间复杂度为O(1)

缺陷:

  • 中间插入删除比较麻烦
  • 不适合遍历

总体来说,deque结合了vector和list的优势,却又没有vector和list的性能那么极致,在大部分场景下都不太常用,所以这里只是简单介绍,并不模拟实现底层结构。

4.4 为什么选择deque作为stack和queue的底层默认容器

原因有两点:

  1. stack和queue不需要遍历(因此stack和queue没有迭代器),只需要在固定的一端或者两端进行操作。
  2. 在stack中元素增长时,deque比vector的效率高(扩容时不需要搬移大量数据);queue中的元素增长
    时,deque不仅效率高,而且内存使用率高

结合了deque的优点,而完美的避开了其缺陷。

总结

这次学习了容器适配器——stack和queue,了解到用容器作为模板的美妙与神奇,极大简化构建容器的代码量。同时简单了解deque的结构和使用场景,进一步理解STL容器的设计。


真诚点赞,手有余香


相关文章
|
8天前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
34 4
|
9天前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
32 4
|
1月前
|
存储 编译器 对象存储
【C++打怪之路Lv5】-- 类和对象(下)
【C++打怪之路Lv5】-- 类和对象(下)
27 4
|
1月前
|
编译器 C语言 C++
【C++打怪之路Lv4】-- 类和对象(中)
【C++打怪之路Lv4】-- 类和对象(中)
23 4
|
1月前
|
存储 程序员 C++
C++常用基础知识—STL库(2)
C++常用基础知识—STL库(2)
69 5
|
1月前
|
存储 算法 调度
【C++打怪之路Lv11】-- stack、queue和优先级队列
【C++打怪之路Lv11】-- stack、queue和优先级队列
33 1
|
1月前
|
存储 安全 C++
【C++打怪之路Lv8】-- string类
【C++打怪之路Lv8】-- string类
21 1
|
1月前
|
存储 自然语言处理 程序员
C++常用基础知识—STL库(1)
C++常用基础知识—STL库(1)
52 1
|
1月前
|
存储 编译器 C语言
【C++打怪之路Lv3】-- 类和对象(上)
【C++打怪之路Lv3】-- 类和对象(上)
16 0
|
1月前
|
算法 数据处理 C++
c++ STL划分算法;partition()、partition_copy()、stable_partition()、partition_point()详解
这些算法是C++ STL中处理和组织数据的强大工具,能够高效地实现复杂的数据处理逻辑。理解它们的差异和应用场景,将有助于编写更加高效和清晰的C++代码。
22 0