喜歡的朋友可以關注收藏一下: 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;
}
運行截圖: