(Boolan)STL与泛型编程作业一

题目:一个整数集 , 该整数集可以有重复元素, 初始为空集合 。可以指定如下指令:

  1. add x 将x加入整数集
  2. del x 删除整数集中所有与x相等的元素
  3. ask x 对整数集中元素x的情况询问
    下面为指令解释,并要求进行如下输出:
  4. add 输出操作后集合中x的个数
  5. del 输出操作前集合中x的个数
  6. ask 先输出0或1表示x是否曾被加入集合(0表示不曾加入),再输出当前集合中x的个数,中间用空格格开。
    提示
    请使用STL中的 set 和multiset 来完成该题

输入
第一行是一个整数n,表示命令数。0<=n<=100000。
后面n行命令。
输出
共n行,每行按要求输出。

样例输入( //第一行是整数,表示为命令数目)
7
add 1
add 1
ask 1
ask 2
del 2
del 1
ask 1
样例输出
1
2
1 2
0 0
0
2
1 0

对于该题目我提供了两个方法来解决问题

方法一:

说明:
  • 该程序是通过一组函数直接实现题目要求的结果
  • 为了保证结果能一次性输出,在程序中采用了queue来暂存操作的输出结果,最后统一输出
  • 为了方便您批改作业,我特地制作了在线测试的程序,程序的在线测试地址:http://rextester.com/VYZSW2883
    • 在线调试帮助:
      • 如何执行

        点击链接进入页面,点击按钮



        即可执行程序了

      • 执行不正确,没有输出(如何输入)

        如果输出不正常,或者没有输入输出,或者不知道如何输入,可以按下图执行


:方法一代码
#include <set>
#include <queue>
#include <iostream>
#include <string>
#include <algorithm>
#include <sstream>

using namespace std;

void controller(multiset<int> &s, queue<string> &rs, set<int> &record);    //通过该函数协调流程
int add(multiset<int> &s, queue<string> &rs, set<int> &record, const int &content);    //添加数据
int del(multiset<int> &s, queue<string> &rs, set<int> &record, const int &content);    //删除数据
int ask(queue<string> &s, multiset<int> &rs, set<int> &record, const int &content, int type = 0);    // 查询数据,type用于区分是否为查询
template<class T>
void printMultiset(queue<T>);    //打印输出结果

int main()
{
    int count;
    multiset<int> s = {};    //创建一个空的容器,用于存放记录
    queue<string> resultSet;    //创建一个空队列,用于存放输出记录
    set<int> record = {};        //创建一个空set,用于存放保存记录
    //cout << "请输入需要操作的步数: \n";
    cin >> count;
    if (count <= 0) count = 1;
    //cout << "还需要输入 " << count << "步操作\n";

    while (count)    //依据输入,循环执行,通过controller调度顺序
    {
        //cout << "还需要输入 " << count << "步操作\n";

        controller(s, resultSet,record);
        count--;
    }

    cout << "\n\n*****************************************\n\n";
    printMultiset(resultSet);    //打印日志

    return 0;
}

void controller(multiset<int> &s, queue<string> &resultSet, set<int> &record)
{
    string cmd;        //命令
    int content;    //内容
    cin >> cmd >> content;
    if ("add" == cmd) {
        add(s, resultSet, record, content);
    }
    else if("del" == cmd)
    {
        del(s, resultSet, record, content);
    }
    else if("ask" == cmd)
    {
        ask(resultSet, s, record, content, 1);//由controller调用
    }
    else 
    {
        cout << "输入错误,请重新输入\n";
    }
}

int add(multiset<int> &s, queue<string> &rs, set<int> &record, const int &content)
{
    s.insert(content);//在集合中加入元素
    ask(rs, s, record, content);//输出操作后集合中x的个数
    record.insert(content);
    return 0;
}

int ask(queue<string> &rs, multiset<int> &target, set<int> &record, const int &content, int type)//type用于区分是否为存入双参数
{
    int count = target.count(content);
    int history = count ? count: record.count(content);//如果count为0,检测该元素是否被删除
    stringstream result;
    result << count;
    string s, scount;
    result >> scount;    //通过stringstream来构造字符串
    if (type) 
    {    //需要存入双参数
        const string a = "1 ", b = "0 ";
        s = (history ? a : b) + scount;
    }
    else 
    {    //存入查询结果即可
        s = scount;
    }

    rs.push(s);//ask的结果保存

    return count;
}

int del(multiset<int> &s, queue<string> &rs, set<int> &record, const int &content)
{
    //删除前需要查询情况
    ask(rs, s, record, content);
    s.erase(content);//删除元素
    return 0;
}

template<class T>
void printMultiset(queue<T> s)
{
    while (!s.empty()) 
    {    //打印日志
        cout << s.front() << endl;
        s.pop();//弹出打印完的日志    
    }
}

方法二:

说明:
  • 这个方法主要是采用了面向对象和泛型编程的思路来实现题目的要求
  • 这个方法,分别有三个单例的class,来封装了multiset、set、queue三个容器,分别来实现保存数据,保存插入记录和输出信息的功能
  • 封装后的最大优势就是,使用者极其简单可以使用封装的过程


    分装后如何使用
  • 为了方便您批改作业,我特地制作了在线测试的程序,程序的在线测试地址:http://rextester.com/SRG5586

    • 在线调试帮助:
      • 如何执行

        点击链接进入页面,点击按钮



        即可执行程序了

      • 执行不正确,没有输出(如何输入)

        如果输出不正常,或者没有输入输出,或者不知道如何输入,可以按下图执行


#ifndef __SET_TEST__HEADER__
#define __SET_TEST__HEADER__

#include <set>
#include <string>
#include <queue>
#include <iostream>
#include <sstream>

using namespace std;

template<typename T>
class Multiset;        //包装了multiset,用于存放数据
template<typename T>
class Recorder;        //记录器,存放记录不会重复,所以包装了set,如果存入了某个数据,在此记录,如果修改了原始数据,此处还有记录,说明该数据被添加过
class ControllerLog;//日志器,包装了queue,用于存放输出信息

template<typename T>
class Multiset    //multiset的包装类
{
private:
    multiset<T>* s;    //实际的容器的指针,用于存放数据
    static Multiset<T>* ms;    //单例模式自己的指针
    Recorder<T>* recorder;    //记录器指针,将添加的数据放入在此
    ControllerLog* log;        //用于控制日志的存储,以便一次输出
    Multiset();//单例
public:
    void add(const T&);    //添加的方法
    void del(const T&);    //删除的方法
    void ask(const T&);    //查询的方法
    static Multiset<T>* getInstance();    //单例模式
    ~Multiset();//析构函数流程
    string geneLog(const T& content, int type = 0);//生成日志,type用于控制不同的日至需求(查询的日志和其他不同)
    void controller();//控制器,用于控制
    void run();//对外的方法,直接调用该方法即可
};

template<typename T>
class Recorder    //记录器,set的包装类
{
private:
    static Recorder<T>* recorder;//单例
    set<T>* s;    //被包装的set
    Recorder();    //单例
public:
    static Recorder<T>* getInstance();//单例
    void addRecord(const T&);//添加一条记录
    int count(const T&) const;//统计数量
    ~Recorder();//析构函数
};

class ControllerLog    //日志器,queue的包装类
{
private:
    queue<string>* q; //被包装对象的指针
    static ControllerLog* cl;//单例
    ControllerLog();//单例
public:
    static ControllerLog* getInstance();//单例
    void addLog(const string &log);//添加一条日至
    void print();//输出所有的日志
    ~ControllerLog();//析构函数
};

template<typename T>
Multiset<T>* Multiset<T>::ms = NULL;//静态成员,需要赋值

template<typename T>
Recorder<T>* Recorder<T>::recorder = NULL;

ControllerLog* ControllerLog::cl = NULL;

#endif // !__SET_TEST__HEADER__



template<typename T>
inline Multiset<T>::Multiset()
{    //构造对象时,构造指针指向的对象
    if (!s)
        s = new multiset<T>();
    if (!log)
        log = ControllerLog::getInstance();
    if (!recorder)
        recorder = Recorder<T>::getInstance();
}

template<typename T>
inline Multiset<T>* Multiset<T>::getInstance()
{    //单例(饿汉模式)
    if (!ms)
        ms = new Multiset<T>();
    return ms;
}

template<typename T>
inline string Multiset<T>::geneLog(const T& content, int type)
{    
    int count = s->count(content);    //查询数据表格中的数量
    int history = count ? count : recorder->count(content);    //如果查询到的count为0,则在Recorder中查询是否存入过
    stringstream result;    //通过stringstream来将得到的int转换为string
    result << count;
    string sresult, scount;
    result >> scount;
    if (type) {        //如果是查询,则依此拼接字符串
        const string a = "1 ", b = "0 ";
        sresult = (history ? a : b) + scount;
    }
    else {        //非查询,依此拼接字符串
        sresult = scount;
    }
    return sresult;
}

template<typename T>
inline void Multiset<T>::controller()
{
    //控制器接受控制台输入
    string cmd;
    T content;
    cout << "请依次输入命令:\n";
    cin >> cmd >> content;
    //依据输入执行不同的方法
    if ("add" == cmd) {
        add(content);
    }
    else if ("del" == cmd)
    {
        del(content);
    }
    else if ("ask" == cmd)
    {
        ask(content);
    }
    else
    {
        cout << "输入错误,请重新输入\n";
    }
}

template<typename T>
inline void Multiset<T>::run() {
    //对外方法,直接调用即可
    int count = 0;
    cout << "请输入命令的条数: ";
    cin >> count;
    count = count >= 0 ? count : 7;
    string x;
    int content;
    //循环接收输入
    while (count) {
        controller();
        count--;
    }
    //打印结果
    cout << "\n\n输出:**************************************\n\n";
    log->print();
}

template<typename T>
inline Multiset<T>::~Multiset()
{    //析构函数释放指针的内存
    if (s) delete s;
    if (log) delete log;
    if (recorder) delete recorder;
    if (ms) delete ms;//最后释放自己
}

template<typename T>
inline void Multiset<T>::add(const T &content)
{    //添加到容器中
    s->insert(content);
    recorder->addRecord(content);//通过记录器,添加一条记录
    log->addLog(geneLog(content));//添加一条输出日志
}

template<typename T>
inline void Multiset<T>::del(const T &content)
{    //通过日志器添加一条日志
    log->addLog(geneLog(content));
    s->erase(content);//数据容器中,清除内容
}

template<typename T>
inline void Multiset<T> ::ask(const T &content)
{
    //添加一条查询记录,以便输出
    log->addLog(geneLog(content, 1));
}

template<typename T>
inline Recorder<T>::Recorder() {
    if (!s)s = new set<T>();//构造对象时,构造指针指向的对象
}

template<typename T>
inline Recorder<T>* Recorder<T>::getInstance()
{
    if (!recorder) recorder = new Recorder<T>();//单例(饿汉模式)
    return recorder;
}

template<typename T>
inline Recorder<T>::~Recorder()
{    // 释放指针指向的对象
    if (s) delete s;
    if (recorder) delete recorder;//最后释放自己
}

template<typename T>
inline void Recorder<T>::addRecord(const T& content)
{
    s->insert(content);//在记录表中添加一个记录
}

template<typename T>
inline int Recorder<T>::count(const T& content) const
{
    return s->count(content);//返回记录表中的数目
}

inline void ControllerLog::addLog(const string &log)
{
    q->push(log);//加入一条日志
}

inline void ControllerLog::print() {
    while (!q->empty())
    {    //遍历打印全部日至
        cout << q->front() << endl;
        q->pop();//将打印完的条目弹出队列
    }
}

inline ControllerLog::ControllerLog() {
    if (!q) q = new queue<string>();    //单例(饿汉模式)
}

inline ControllerLog* ControllerLog::getInstance()
{
    if (!cl) cl = new ControllerLog();    //单例
    return cl;
}

inline ControllerLog::~ControllerLog()
{
    if (q) delete q;
    if (cl) delete cl;    //最后释放自己
}


int main()
{
    Multiset<int>* s = Multiset<int>::getInstance();//单例模式获取对象
    s->run();//调用方法执行

    system("pause");
    return 0;
}
内容概要:《2024年中国城市低空经济发展指报告》由36氪研究院发布,指出低空经济作为新质生产力的代表,已成为中国经济新的增长点。报告从发展环境、资金投入、创新能力、基础支撑和发展成效五个维度构建了综合指评价体系,评估了全国重点城市的低空经济发展状况。北京和深圳在总指中名列前茅,分别以91.26和84.53的得分领先,展现出强大的资金投入、创新能力和基础支撑。低空经济主要涉及无人机、eVTOL(电动垂直起降飞行器)和直升机等产品,广应用于农业、物流、交通、应急救援等领域。政策支持、市场需求和技术进步共同推动了低空经济的快速发展,预计到2026年市场规模将突破万亿元。 适用人群:对低空经济发展感兴趣的政策制定者、投资者、企业和研究人员。 使用场景及目标:①了解低空经济的定义、分类和发展驱动力;②掌握低空经济的主要应用场景和市场规模预测;③评估各城市在低空经济发展中的表现和潜力;④为政策制定、投资决策和企业发展提供参考依据。 其他说明:报告强调了政策监管、产业生态建设和区域融合错位的重要性,提出了加强法律法规建设、人才储备和基础设施建设等建议。低空经济正加速向网络化、智能化、规模化和集聚化方向发展,各地应找准自身比较优势,实现差异化发展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值