【C++】STL中的容器适配器 stack queue 和 priority_queue 的模拟实现

简介: 【C++】STL中的容器适配器 stack queue 和 priority_queue 的模拟实现

一、容器适配器

1、什么是容器适配器

适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结),该种模式是将一个类的接口转换成客户希望的另外一个接口。

例如我们常见的充电器就是一种适配器,它将我们常用的220V交流电压转化为4,5V (或者其他更高的电压) 的直流电压来给我们的电子设备进行充电。

2、STL标准库中的容器适配器

虽然stackqueuepriority_queue中也可以存放元素,但在STL中并没有将其划分在容器的行列,而是将其称为容器适配

器,这是因为stack和队列只是对其他容器的接口进行了包装,STL中stackqueue默认使用dequepriority_queue默认使用了vector

二、stack的模拟实现

1、stack的简单介绍

相关文档

stack的底层容器可以是任何标准的容器类模板或者一些其他特定的容器类,但这些容器类应该支持以下操作:

  • empty:判空操作
  • back:获取尾部元素操作
  • push_back:尾部插入元素操作
  • pop_back:尾部删除元素操作

标准容器vectordequelist均符合这些需求,默认情况下,如果没有为stack指定特定的底层容器,默认情况下使用deque

2、栈的模拟实现

为了栈的通用性,这里我们使用模板来进行模拟栈,关于栈的底层容器这里我们选择vector来进行模拟实现。

template<class T, class Container = vector<T>>
class stack
{
public:
  //栈的插入
  void push(const T& val)
  {
    //使用底层容器中尾插函数进行插入,栈只能进行栈顶插入和删除
    _con.push_back(val);
  }
  //栈的删除
  void pop()
  {
    //使用底层容器中尾删函数进行插入,栈只能进行栈顶插入和删除
    _con.pop_back();
  }
  //获取栈顶元素
  T& top()
  {
    //返回底层容器中最后一个数据
    return _con.back();
  }
  //const 版本
  const T& top() const
  {
    return _con.back();
  }
  //获取数据个数
  size_t size() const
  {
    //返回底层容器中数据的个数
    return _con.size();
  }
  //判空函数
  bool empty() const
  {
    //对底层容器进行判空
    return _con.empty();
  }
private:
  //成员变量是一个容器创建的对象
  Container _con;
};

三、queue的模拟实现

1、queue的简单介绍

相关文档

queue底层容器可以是标准容器类模板之一,也可以是其他专门设计的容器类。该底层容器应至少支持以下操作:

  • empty:检测队列是否为空
  • size:返回队列中有效元素的个数
  • front:返回队头元素的引用
  • back:返回队尾元素的引用
  • push_back:在队列尾部入队列
  • pop_front:在队列头部出队列

标准容器类dequelist满足了这些要求。默认情况下,如果没有为queue实例化指定容器类,则使用标准容器deque

2、queue的模拟实现

为了queue的通用性,这里我们使用模板来进行模拟queue,关于queue的底层容器这里我们选择list来进行模拟实现。

template<class T, class Container = list<T>>
class queue
{
public:
  //队列的插入
  void push(const T& val)
  {
    //使用底层容器中尾插函数进行插入,队列只能进行队尾插入
    _com.push_back(val);
  }
  //队列的删除
  void pop()
  {
    //使用底层容器中头删函数进行删除,队列只能进行队头删除
    _com.pop_front();
  }
  //获取队头数据
  T& front()
  {
    //返回底层容器中第一个数据
    return _com.front();
  }
  //const版本
  const T& front() const
  {
    return _com.front();
  }
  //获取队尾数据
  T& back()
  {
    //返回底层容器中最后一个数据
    return _com.back();
  }
  //const版本
  const T& back() const
  {
    return _com.back();
  }
  //获取数据个数
  size_t size() const
  {
    //返回底层容器中数据的个数
    return _com.size();
  }
  //判空函数
  bool empty() const
  {
    //对底层容器进行判空
    return _com.empty();
  }
private:
  //成员变量是一个容器创建的对象
  Container _com;
};

四、priority_queue的模拟实现

1、priority_queue的简单介绍

相关文档

优先队列是一种容器适配器,它其实就是我们数据结构中的,默认情况下priority_queue是大堆。

priority_queue底层容器可以是任何标准容器类模板,也可以是其他特定设计的容器类。容器应该可以通过随机访问迭代器访问,并支持以下操作:

  • empty:检测容器是否为空
  • size:返回容器中有效元素个数
  • front:返回容器中第一个元素的引用
  • push_back:在容器尾部插入元素
  • pop_back:删除容器尾部元素

标准容器类vectordeque满足这些需求。默认情况下,如果没有为特定的priority_queue类实例化指定容器类,则使用vector

2、priority_queue的模拟实现

与前面的栈与队列一样priority_queue前两个模板参数都类似,但是priority_queue要有第三个模板参数,这个参数表示按照什么方式进行比较,即建立大堆还是小堆。

//第三个参数是比较方式,需要传递一个仿函数来确定比较方式,默认传递的是less<T>,表示建大堆
template<class T, class Container = vector<T>, class Comper = less<T>>
class priority_queue
{
public:
  //获取堆顶数据
  const T& top() const
  {
    //返回底层容器的第一个数据
    return _con.front();
  }
  //获取数据个数
  size_t size() const
  {
    //返回底层容器的数据个数
    return _con.size();
  }
  //判空函数
  bool empty() const
  {
    //判断底层容器是否为空
    return _con.empty();
  }
  //堆的插入
  void push(const T& val)
  {
    //从尾部插入
    _con.push_back(val);
    int child = _con.size() - 1;
    //向上调整重新建堆
    AdjustUp(child);
  }
  //堆的删除
  void pop()
  {
    //检查堆是否为空
    assert(!_con.empty());
    //交换堆顶与最后一个数据
    swap(_con.front(), _con.back());
    //删除最后一个数据
    _con.pop_back();
    //从堆顶进行向下调整,重新建堆
    AdjustDown(0);
  }
private:
  //向上调整算法
  void AdjustUp(int child)
  {
    Comper com;
    int parent = (child - 1) / 2;
    while (child > 0)
    {
      //这里使用了仿函数来判断建立什么堆
      //比较的位置(_con[parent], _con[child])是不能换的!!!
      if (com(_con[parent], _con[child]))
      {
        swap(_con[parent], _con[child]);
        child = parent;
        parent = (child - 1) / 2;
      }
      else
      {
        break;
      }
    }
  }
  //向下调整算法
  void AdjustDown(int parent)
  {
    Comper com;
    //默认左孩子更符合建堆的要求
    int child = parent *2 + 1;
    while (child < _con.size())
    {
      if (child + 1 < _con.size() && Comper()(_con[child], _con[child + 1]))
      {
        ++child;
      }
      if (com(_con[parent], _con[child]))
      {
        swap(_con[parent], _con[child]);
        parent = child;
        child = parent * 2 + 1;
      }
      else
      {
        break;
      }
    }
  }
  //成员变量是一个容器创建的对象
  Container _con;
};
相关文章
|
3月前
|
存储 搜索推荐 C++
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器2
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器
76 2
|
2月前
|
存储 设计模式 C++
【C++】优先级队列(容器适配器)
本文介绍了C++ STL中的线性容器及其适配器,包括栈、队列和优先队列的设计与实现。详细解析了`deque`的特点和存储结构,以及如何利用`deque`实现栈、队列和优先队列。通过自定义命名空间和类模板,展示了如何模拟实现这些容器适配器,重点讲解了优先队列的内部机制,如堆的构建与维护方法。
48 0
|
3月前
|
存储 编译器 C++
【C++篇】揭开 C++ STL list 容器的神秘面纱:从底层设计到高效应用的全景解析(附源码)
【C++篇】揭开 C++ STL list 容器的神秘面纱:从底层设计到高效应用的全景解析(附源码)
94 2
|
1月前
|
监控 NoSQL 时序数据库
《docker高级篇(大厂进阶):7.Docker容器监控之CAdvisor+InfluxDB+Granfana》包括:原生命令、是什么、compose容器编排,一套带走
《docker高级篇(大厂进阶):7.Docker容器监控之CAdvisor+InfluxDB+Granfana》包括:原生命令、是什么、compose容器编排,一套带走
260 77
|
9天前
|
Ubuntu NoSQL Linux
《docker基础篇:3.Docker常用命令》包括帮助启动类命令、镜像命令、有镜像才能创建容器,这是根本前提(下载一个CentOS或者ubuntu镜像演示)、容器命令、小总结
《docker基础篇:3.Docker常用命令》包括帮助启动类命令、镜像命令、有镜像才能创建容器,这是根本前提(下载一个CentOS或者ubuntu镜像演示)、容器命令、小总结
77 6
《docker基础篇:3.Docker常用命令》包括帮助启动类命令、镜像命令、有镜像才能创建容器,这是根本前提(下载一个CentOS或者ubuntu镜像演示)、容器命令、小总结
|
1月前
|
监控 Docker 容器
在Docker容器中运行打包好的应用程序
在Docker容器中运行打包好的应用程序
|
20天前
|
Ubuntu Linux 开发工具
docker 是什么?docker初认识之如何部署docker-优雅草后续将会把产品发布部署至docker容器中-因此会出相关系列文章-优雅草央千澈
Docker 是一个开源的容器化平台,允许开发者将应用程序及其依赖项打包成标准化单元(容器),确保在任何支持 Docker 的操作系统上一致运行。容器共享主机内核,提供轻量级、高效的执行环境。本文介绍如何在 Ubuntu 上安装 Docker,并通过简单步骤验证安装成功。后续文章将探讨使用 Docker 部署开源项目。优雅草央千澈 源、安装 Docker 包、验证安装 - 适用场景:开发、测试、生产环境 通过以上步骤,您可以在 Ubuntu 系统上成功安装并运行 Docker,为后续的应用部署打下基础。
docker 是什么?docker初认识之如何部署docker-优雅草后续将会把产品发布部署至docker容器中-因此会出相关系列文章-优雅草央千澈
|
9天前
|
Kubernetes Linux 虚拟化
入门级容器技术解析:Docker和K8s的区别与关系
本文介绍了容器技术的发展历程及其重要组成部分Docker和Kubernetes。从传统物理机到虚拟机,再到容器化,每一步都旨在更高效地利用服务器资源并简化应用部署。容器技术通过隔离环境、减少依赖冲突和提高可移植性,解决了传统部署方式中的诸多问题。Docker作为容器化平台,专注于创建和管理容器;而Kubernetes则是一个强大的容器编排系统,用于自动化部署、扩展和管理容器化应用。两者相辅相成,共同推动了现代云原生应用的快速发展。
64 11
|
26天前
|
存储 Kubernetes 开发者
容器化时代的领航者:Docker 和 Kubernetes 云原生时代的黄金搭档
Docker 是一种开源的应用容器引擎,允许开发者将应用程序及其依赖打包成可移植的镜像,并在任何支持 Docker 的平台上运行。其核心概念包括镜像、容器和仓库。镜像是只读的文件系统,容器是镜像的运行实例,仓库用于存储和分发镜像。Kubernetes(k8s)则是容器集群管理系统,提供自动化部署、扩展和维护等功能,支持服务发现、负载均衡、自动伸缩等特性。两者结合使用,可以实现高效的容器化应用管理和运维。Docker 主要用于单主机上的容器管理,而 Kubernetes 则专注于跨多主机的容器编排与调度。尽管 k8s 逐渐减少了对 Docker 作为容器运行时的支持,但 Doc
127 5
容器化时代的领航者:Docker 和 Kubernetes 云原生时代的黄金搭档
|
1月前
|
关系型数据库 应用服务中间件 PHP
实战~如何组织一个多容器项目docker-compose
本文介绍了如何使用Docker搭建Nginx、PHP和MySQL的环境。首先启动Nginx容器并查看IP地址,接着启动Alpine容器并安装curl测试连通性。通过`--link`方式或`docker-compose`配置文件实现服务间的通信。最后展示了Nginx配置文件和PHP代码示例,验证了各服务的正常运行。
52 3
实战~如何组织一个多容器项目docker-compose