【C++】容器适配器结构的设计

目录

介绍:

一,queue结构的设计

二,priority_queue结构设计

三,stack结构设计


介绍:

适配器

        适配器是一种设计模式,而设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计的总结,该模式是将一个类的接口转换成另一个类的接口。比如我们常用的交流适配器、电源插口适配器等,如下图:

容器模板

        模板的使用可以帮助我们接收万能类型,平常我们最多用的也就是普通类型的使用,其实模板也可接收容器类型,并像函数缺省参数一样,进行缺省参数的使用,即函数参数传递的是对象,而模板传递的是类型,使用如下:

template <class T = int, class Container = vector<T>>  //第一个匹配普通类型,默然类型为int,第二个为容器类型,默认类型为vector<T>
//.........  这里省略了具体的类模板或函数模板

        在C++标准库中,有一些常用的容器适配器。容器适配器是将容器经过特定的设计,完成特定的功能,如queue队列结构、stack栈结构、priority_queue优先队列结构等。这里都需要传入特定的容器,将其接口经过特定的修改,使其具有独特的功能。

        这里需注重强调一下,容器适配器不是容器,因此它没有迭代器,只有容器才有迭代器。因此,容器适配器不支持范围for等底层用迭代器实现的语法结构。


一,queue结构的设计

        我们先来观察queue的底层实现结构,如下图:

        这里,我们实现队列机制很简单,这里我们直接用Container容器接口功能即可,在编译阶段时对其进行实例化,具体逻辑解说请看下面:

//封装容器类型Container,可以使用容器内的所有接口功能,这里我们不用容器类型的管底层是如何实现的
template<class T = int, class Container = std::deque<T>>//模板缺省值的使用,跟函数缺省值一样
class queue
{
public:
    //下面直接使用容器中的接口功能即可,唯一要注意的是容器类型中必须存在此接口
    void push(const T x = T())
    {
        con.push_back(x);
    }
    void pop()
    {
        con.pop_front();
    }
    const T& front()
    {
        return con.front();
    }
    const T& back()
    {
        return con.back();
    }
    const size_t size()
    {
        return con.size();
    }
    bool empty()
    {
        return con.empty();
    }
private:
    Container con;  //在编译阶段对其进行实例化,调用时会调用其的构造函数
};


二,priority_queue结构设计

        priority_queue底层用堆数据结构实现,我们先观察以下类型接口:

        上图中,第一个参数T表示数据类型;第二个参数表示容器类型,不说明时默认为vector<T>类型;第三个参数用来说明建大堆还是小堆,不说明时默认为less<T>类(默认 “ < ”,第一个参数小于第二个参数)建大堆,要想建小堆需要“ 大于 ”,即greater<T>类 (默认 “ > ”,第一个参数大于第二个参数)。

        这里的第三个参数跟sort排序算法的第三个参数效果相同,都是用来控制功能效果。不同的是这里传递的是类less或greater的类类型,即greater<T>或less<T>,而sort的第三个参数是类less或greater的函数对象,即greater<T>()或less<T>()。

        在设计这方面的结构前,我们先了解以下仿函数。仿函数其实就是在类中重载一个“ () ” 的函数,此函数通常也叫函数对象,即仿函数或函数对象是一个定义了含有 operator() 成员函数的类,且该函数可以像普通函数一样被调用。

        这里需说明的是,从本质上来讲仿函数其实是一个类,而不是一个函数。它是一种行为类似函数的对象,可以像普通函数那样调用,有参数、有返回值。以下代码设计了一个仿函数:   

#include <iostream>
using namespace std;
class A
{
public:bool operator()(int a, int b) {return a > b;}
private:int a;int b;
};
int main()
{A X;cout << X(5, 6) << endl; //直接使用类对象调用//等效于以下代码cout << X.operator()(5, 6) << endl;return 0;
}

        实现此适配器跟实现堆结构一样,这里唯一要注意的是要运用第三个参数控制大堆结构和小堆结构,默认情况传递less建大堆。具体的代码细节和相关注意点如下:

template <class T>
class less
{
public:
    bool operator()(const T& x, const T& y) {
        return x < y;
    }
};
template <class T>
class greater
{
public:
    bool operator()(const T& x, const T& y) {
        return x > y;
    }
};
template <class T = int, class Container = std::vector<T>, class Compare = less<T> >
class priority_queue
{
public:
    void Adjustup(Container& c)  //向上调整算法建堆
    {
        int child = c.size() - 1;
        int parent = (child - 1) / 2;

        //注意: 这里不能使用Container::iterator it;这里使用模板类的成员,必须指定具体类型才可使用,编译器识别不了具体指类型还是静态变量
        //编译器这里是分开编译的,先编译模板,后编译实例化,然后两个地方合在一起
        //当编译到模板这块还不知道Container是什么具体类型,无法使用迭代器,模板都存在这个问题
        //这里可以使用template来说明是其类型,进行推演,等到实例化然后再去里面取
        //不用template可用auto直接万能接收类型,等编译到实例化时进行确定

        auto it = c.begin();  //这里不用函数和类,因此不能使用模板,直接auto识别即可
        //例如: typedef std::vector<T>::iterator iterator; 错误,编译器识别不出,一样的原理
        while (parent >= 0 && comp(*(it + parent), *(it + child))) {
            std::swap(*(it + child), *(it + parent));
            child = parent;
            parent = (child - 1) / 2;
        }
    }
    void Adjustdown(Container& c) {  //向下调整算法建堆
        int parent = 0;
        int child = parent * 2 + 1;
        auto it = c.begin();
        while (child < c.size()) {
            if (child + 1 < c.size() && comp(*(it + child), *(it + child + 1))) {
                child++;
            }
            if (comp(*(it + parent), *(it + child))) {
                std::swap(*(it + child), *(it + parent));
                parent = child;
                child = parent * 2 + 1;
            }
            else {
                break;
            }
        }
    }
    priority_queue()
    {   }
    template <class InputIterator>//与上同理,直接使用万能推演,编译到这块时,会根据后面进行推演
    priority_queue(InputIterator first, InputIterator last)
        :c(first, last)
    {
        for (int i = (c.size() - 1) / 2; i >= 0; i--) {
            Adjustdown(c);
        }
    }
    bool empty() const
    {
        return c.empty();
    }
    size_t size() const
    {
        return c.size();
    }
    const T& top() const
    {
        return c.front();
    }
    void push(const T& x)
    {
        c.push_back(x);
        Adjustup(c);
    }
    void pop()
    {
        std::swap(c.front(), c.back());
        c.pop_back();
        Adjustdown(c);
    }
private:
    Container c;
    Compare comp;
};


三,stack结构设计

        这里的stack实现机制与queue结构逻辑一样,直接套用容器类型模板,运用其接口功能实现专门结构的功能即可。代码如下:

template<class T, class Container = std::deque<T>>
class stack
{
public:
    void push(const T x = T())
    {
        con.push_back(x);
    }
    void pop()
    {
        con.pop_back();
    }
    const T& top()
    {
        return con.back();
    }
    const size_t size()
    {
        return con.size();
    }
    bool empty()
    {
        return con.empty();
    }
private:
    Container con;
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/679534.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【机器学习】全网最全模型评价指标(性能指标、YOLOv5训练结果分析、轻量化指标、混淆矩阵详解)【基础收藏】

&#x1f951; Welcome to Aedream同学 s blog! &#x1f951; 文章目录 模型性能指标常见指标ROC/AUCROC & PRC多分类问题——混淆矩阵 计算结果分析——以YOLO v5为例1. confusion_matrix.png(混淆矩阵)2. F1_curve&#xff1a;3. labels.jpg4. labels_corrrelogram.jpg5…

免费分享一套PyQt6学生信息管理系统 Python管理系统 Python源码,挺漂亮的

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的PyQt6学生信息管理系统 Python管理系统 Python源码&#xff0c;分享下哈。 项目视频演示 【免费】PyQt5 学生信息管理系统 Python管理系统 Python源码 Python毕业设计_哔哩哔哩_bilibili【免费】PyQt5 学生…

揭秘:15条黄金法则,让你的GPT聊天提示效率翻倍!(一)

你的 ChatGPT 响应的好坏完全取决于你使用的ChatGPT 提示。 事实是&#xff0c;ChatgPT对于潜在客户开发、内容创建甚至外展都非常有效。 但大多数人只是使用人工智能来创建内容。 当然&#xff0c;它有时可以产生一些纯文本。也就是说&#xff0c;如果你只使用正确的提示。…

Junit常用注解

注解是方法的“标签” 说明每个方法的“职责” Q:总共有那些注解? 参见官方的API文档 0.常用主机及其特点 BeforeClass 只会执行一次必须用static修饰常用来初始化测试需要的变量 Before 会执行多次&#xff08;只要写一次&#xff09;在每个Test执行执行之前执行可以和…

fast.ai 机器学习笔记(一)

机器学习 1&#xff1a;第 1 课 原文&#xff1a;medium.com/hiromi_suenaga/machine-learning-1-lesson-1-84a1dc2b5236 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 来自机器学习课程的个人笔记。随着我继续复习课程以“真正”理解它&#xff0c;这些笔记将继续更…

精品springboot疫苗发布和接种预约系统

《[含文档PPT源码等]精品基于springboot疫苗发布和接种预约系统[包运行成功]》该项目含有源码、文档、PPT、配套开发软件、软件安装教程、项目发布教程、包运行成功&#xff01; 软件开发环境及开发工具&#xff1a; Java——涉及技术&#xff1a; 前端使用技术&#xff1a;…

代码随想录算法训练营第四十九天(动态规划篇)| 474. 一和零, 完全背包理论基础

474. 一和零 题目链接&#xff1a;https://leetcode.cn/problems/ones-and-zeroes/submissions/501607337/ 思路 之前的背包问题中&#xff0c;我们对背包的限制是容量&#xff0c;即每个背包装的物品的重量和不超过给定容量&#xff0c;这道题的限制是0和1的个数&#xff0…

基于微信小程序的在线课堂的研究与实现,附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

fast.ai 机器学习笔记(四)

机器学习 1&#xff1a;第 11 课 原文&#xff1a;medium.com/hiromi_suenaga/machine-learning-1-lesson-11-7564c3c18bbb 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 来自机器学习课程的个人笔记。随着我继续复习课程以“真正”理解它&#xff0c;这些笔记将继续…

移动光猫gs3101超级密码及改桥接模式教程

文章目录 超级管理员账号改桥接模式路由器连接光猫&#xff0c;PPPOE拨号即可&#xff01;附录&#xff1a;如果需要改桥接的话不知道拨号密码咋办打开光猫Telnet功能Telnet 登录 参考文章 移动光猫吉比特GS3101超级账号获取更改桥接 移动光猫gs3101超级密码及改桥接模式教程 …

(2)长距离

文章目录 2.1 Andruav Android Cellular 2.2 Blicube RLINK P900 2.3 ClearSky Airlink 4G LTE遥测技术 2.4 CRSF/ELRS Telemetry 2.5 CUAV P8 Radio 2.6 CUAV P9 Radio 2.7 DragonLink 2.8 Holybro 900Mhz XBP9X无线电遥测设备 2.9 Holybro Microhard P900无线电遥测…

Idea Git Review插件

idea git plugin 添加了一些常用的小插件 可以右键打开git bash窗口 可以右键选中文字点击baidu fanyi 可以通过搜索git用户名 指定开始时间查询某个版本自己提交的所有代码文件 可以通过点击蓝色行数&#xff0c;跳转到指定的改动代码块 资源地址&#xff1a; git-pl…

flask+python高校学生综合测评管理系统 phl8b

系统包括管理员、教师和学生三个角色&#xff1b; 。通过研究&#xff0c;以MySQL为后端数据库&#xff0c;以python为前端技术&#xff0c;以pycharm为开发平台&#xff0c;采用vue架构&#xff0c;建立一个提供个人中心、学生管理、教师管理、课程类型管理、课程信息管理、学…

【XR806开发板试用】轻松连上华为云实现物联网

本文为极术社区XR806试用活动文章。 一.开始 偶然的机会在网上看到了鸿蒙开发板的试用,作为一个"老鸿蒙"岂能放弃这个机会,报名之后不出意料地得到了使用名额,在此感谢极术社区. 收到开发板之后其实还有点失望了,就那么一个小小的核心板,其他啥也没有,连一根数据线…

AI跟踪报道第28期-新加坡内哥谈技术-本周AI新闻:Gemini Ultra 来了

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

Vulnhub靶机:hacksudo-ProximaCentauri

一、介绍 运行环境&#xff1a;Virtualbox 攻击机&#xff1a;kali&#xff08;10.0.2.15&#xff09; 靶机&#xff1a;hacksudo-ProximaCentauri&#xff08;10.0.2.51&#xff09; 目标&#xff1a;获取靶机root权限和flag 靶机下载地址&#xff1a;https://www.vulnhu…

STM32 7-8

目录 ADC AD单通道 AD多通道 DMA DMA转运数据 DMAAD多通道 ADC AD单通道 AD.c #include "stm32f10x.h" // Device header/*** brief 初始化AD所需要的所有设备* param 无* retval 无*/ void AD_Init(void) {RCC_APB2PeriphClockCmd(RCC_AP…

Java 集合、迭代器

Java 集合框架主要包括两种类型的容器&#xff0c;一种是集合&#xff08;Collection&#xff09;&#xff0c;存储一个元素集合&#xff0c;另一种是图&#xff08;Map&#xff09;&#xff0c;存储键/值对映射。Collection 接口又有 3 种子类型&#xff0c;List、Set 和 Queu…

使用Cargo创建、编译与运行Rust项目

在 Rust 开发中&#xff0c;Cargo 是一个非常重要的工具&#xff0c;它负责项目的构建、管理和依赖管理。以下是如何使用 Cargo 创建、编译和运行 Rust 项目的详细步骤。 1. 创建新项目 首先确保你已经在计算机上安装了 Rust 和 Cargo。然后&#xff0c;在命令行中输入以下命…

Github 2024-02-12 开源项目日报 Top10

根据Github Trendings的统计&#xff0c;今日(2024-02-12统计)共有10个项目上榜。根据开发语言中项目的数量&#xff0c;汇总情况如下&#xff1a; 开发语言项目数量Rust项目3Python项目3JavaScript项目1TypeScript项目1C项目1C项目1PowerShell项目1非开发语言项目1 SubQuery…