喜欢的朋友可以关注收藏一下: http://blog.csdn.NET/qq_31201973
本文如有错误,请及时私信我。
原版要求:
题目:一个整数集 , 该整数集可以有重复元素, 初始为空集合 。可以指定如下指令:
1. add x 将x加入整数集
2. del x 删除整数集中所有与x相等的元素
3. ask x 对整数集中元素x的情况询问
下面为指令解释,并要求进行如下输出:
1. add 输出操作后集合中x的个数
2. del 输出操作前集合中x的个数
3. 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
首先我为了以后扩展考虑把对数集操作放到函数中来进行所在我做了这样的定义
// multiset.h
#ifndef __MULTISET_H__
#define __MULTISET_H__
#include<iostream>
#include<cstdlib>
#include<string>
#include <set>
#include <stdexcept>
#include <algorithm>
using namespace std;
namespace guo
{
void int_com(int& n, int& value, string& command, multiset<int>& ms2, set<int>& s2) //本程序添加了交互,经测试逻辑无误
{;}
}
#endif
然后在main()函数中使用它:
guo::int_com(n, value, command, ms2, s2);
指令的个数和操作数才用int型,指令才用c++ string类型。因为ask命令要求显示这个操作数是否加入过,因为之前可能执行过del命令,所以我才用两个容器来做。因为考虑操作数的重复性,所以第一个容器才用multiset。而第二个容器作用是显示操作数是否加入过,可以不重复,为了节省空间,所以才用非重复的容器set.
int n, value; //n为指令数,value为要操作的值
string command;
multiset<int> ms2;
set<int> s2; //因为不允许重复,节省空间
题目中命令数的判断我提供了两种方法:
if (n <= 0 || n > 100000) //题目要求输入边界判断方法一
{
while (1)
{
cout << "命令数范围非法,请重新输入命令(整数0<=n<=100000):";
cin >> n;
if (n>0 && n<=100000)
{
break;
}
}
}
最开始的办法是这个,这个时候我想起linux之父关于编程品味的演讲,举的例子是消除判断语句,改善程序的效率。我就依据这个做了一个改善重构,发现程序的效率和行数发生了很大的变化。
while (n <= 0 || n > 100000) //题目要求输入边界判断方法二(改进); linux之父在演讲中提到把判断语句减少是一种好的编程品味,这个改进就是基于此改进从而增加程序效率;
{
cout << "命令数范围非法,请重新输入命令(整数0<=n<=100000):";
cin >> n;
}
这样在我还没用实际开始程序编写之前我就搭好了框架,让程序跑了起来
// multiset.cpp
#include<iostream>
#include<cstdlib>
#include"multiset.h"
#include<string>
#include <set>
#include <stdexcept>
#include <algorithm>
using namespace std;
int main()
{
int n, value; //n为指令数,value为要操作的值
string command;
multiset<int> ms2;
set<int> s2; //因为不允许重复,节省空间
cout << "请输入要输入的指令数: ";
cin >> n;
//if (n <= 0 || n > 100000) //题目要求输入边界判断方法一
//{
// while (1)
// {
// cout << "命令数范围非法,请重新输入命令(整数0<=n<=100000):";
// cin >> n;
// if (n>0 && n<=100000)
// {
// break;
// }
// }
//}
while (n <= 0 || n > 100000) //题目要求输入边界判断方法二(改进); linux之父在演讲中提到把判断语句减少是一种好的编程品味,这个改进就是基于此改进从而增加程序效率;
{
cout << "命令数范围非法,请重新输入命令(整数0<=n<=100000):";
cin >> n;
}
guo::int_com(n, value, command, ms2, s2);
system("pause");
return 0;
}
之后我只需要对int_com(int& n, int& value, string& command, multiset<int>& ms2, set<int>& s2)里增加代码就好了。
首先对命令数进行处理
for (int i = 0; i < n; i++)
然后是输入及判断,我搭起了这样的框架。
cout << "请输入命令" << i + 1 << ": ";
cin >> command >> value;
if (command == "add")
{
}
else if (command == "ask") //经测试方法一和方法二都能实现功能
{
}
else if (command == "del")
{
}
对于add命令,采用insert函数插入,count函数显示数量,并且我采用了异常处理。
if (command == "add")
{
try {
ms2.insert(value);
s2.insert(value);
cout << "数集中value的数量: "<<ms2.count(value) << endl;
}
catch (exception& p) {
cout << "i=" << i << " " << p.what() << endl;
cout << "数集中value的数量: " << ms2.count(value) << endl;
abort();
}
}
ask命令我采用了两种方法,显然第二种效率更高。
else if (command == "ask") //经测试方法一和方法二都能实现功能
{
//multiset<int>::iterator iter = s2.find(value); //方法一
//if (iter != s2.end())
//{
// cout << 1 << " " << ms2.count(value) << endl;
//}
//else
//{
// cout << 0 << " " << ms2.count(value) << endl;
//}
if (s2.count(value)) //方法二
{
cout << 1 << " " << ms2.count(value) << endl;
}
else
{
cout << 0 << " " << ms2.count(value) << endl;
}
}
删除我采用的是count函数和erase函数来处理
else if (command == "del")
{
cout << "删除前" << value << "的个数:" << ms2.count(value) << endl;
ms2.erase(value);
}
这样整个程序就写好了
完整版代码:
// multiset.h
#ifndef __MULTISET_H__
#define __MULTISET_H__
#include<iostream>
#include<cstdlib>
#include<string>
#include <set>
#include <stdexcept>
#include <algorithm>
using namespace std;
namespace guo
{
void int_com(int& n, int& value, string& command, multiset<int>& ms2, set<int>& s2) //本程序添加了交互,经测试逻辑无误
{
for (int i = 0; i < n; i++)
{
cout << "请输入命令" << i + 1 << ": ";
cin >> command >> value;
if (command == "add")
{
try {
ms2.insert(value);
s2.insert(value);
cout << "数集中value的数量: "<<ms2.count(value) << endl;
}
catch (exception& p) {
cout << "i=" << i << " " << p.what() << endl;
cout << "数集中value的数量: " << ms2.count(value) << endl;
abort();
}
}
else if (command == "ask") //经测试方法一和方法二都能实现功能
{
//multiset<int>::iterator iter = s2.find(value); //方法一
//if (iter != s2.end())
//{
// cout << 1 << " " << ms2.count(value) << endl;
//}
//else
//{
// cout << 0 << " " << ms2.count(value) << endl;
//}
if (s2.count(value)) //方法二
{
cout << 1 << " " << ms2.count(value) << endl;
}
else
{
cout << 0 << " " << ms2.count(value) << endl;
}
}
else if (command == "del")
{
cout << "删除前" << value << "的个数:" << ms2.count(value) << endl;
ms2.erase(value);
}
}
}
}
#endif
// multiset.cpp
#include<iostream>
#include<cstdlib>
#include"multiset.h"
#include<string>
#include <set>
#include <stdexcept>
#include <algorithm>
using namespace std;
int main()
{
int n, value; //n为指令数,value为要操作的值
string command;
multiset<int> ms2;
set<int> s2; //因为不允许重复,节省空间
cout << "请输入要输入的指令数: ";
cin >> n;
//if (n <= 0 || n > 100000) //题目要求输入边界判断方法一
//{
// while (1)
// {
// cout << "命令数范围非法,请重新输入命令(整数0<=n<=100000):";
// cin >> n;
// if (n>0 && n<=100000)
// {
// break;
// }
// }
//}
while (n <= 0 || n > 100000) //题目要求输入边界判断方法二(改进); linux之父在演讲中提到把判断语句减少是一种好的编程品味,这个改进就是基于此改进从而增加程序效率;
{
cout << "命令数范围非法,请重新输入命令(整数0<=n<=100000):";
cin >> n;
}
guo::int_com(n, value, command, ms2, s2);
system("pause");
return 0;
}
运行截图: