很不错的题, 有助于理解multiset的具体实际实现过程, 同时熟悉了map
的使用和功能
#include <iostream>
#include <map>
using namespace std;
template <typename T>
class MultiSet {
public:
MultiSet() {}
MultiSet(const MultiSet& set);
MultiSet& operator=(const MultiSet& set);
void insert(const T& ele);
bool erase(const T& ele);
MultiSet Union(const MultiSet& set);
MultiSet Intersection(const MultiSet& set);
template <typename T1>
friend ostream& operator<<(ostream& out, const MultiSet<T1>& set);
private:
// map中存放的元素为T 和 int即第一个数存放的是数,
// 而第二个数存的是该数在map中的数目
// map中的元素不可重复
// 这里是利用了map来实现multiset的功能设计
// 最后是利用了int的值来输出相同的数
map<T, int> my_map;
};
template<typename T>
MultiSet<T>::MultiSet(const MultiSet& set) {
// map 容器重载=操作符,所以此处直接赋值即可
my_map = set.my_map;
}
template<typename T>
MultiSet<T>& MultiSet<T>::operator=(const MultiSet& set) {
// multiset实现的重载操作符=,实际上是直接运用了map重载的=
my_map = set.my_map;
return *this;
}
template<typename T>
void MultiSet<T>::insert(const T& ele) {
if (my_map.count(ele) == 1) {
my_map[ele]++;
} else {
// map重载了下标操作符, my_map[ele] = 1, 即是向map容器中添加了新的元素,并且该元素的
// int值为1;
my_map[ele] = 1;
}
}
template<typename T>
bool MultiSet<T>::erase(const T& ele) {
if (!my_map.count(ele)) {
return false;
} else {
// my_map[ele] == 0就表示map中没有了这个元素吗???不懂
my_map[ele]--;
// 每erase一次int的值-1, 当int的值为0是, 将对应map中的元素彻底删除掉
if (!my_map[ele]) {
typename map<T, int>::iterator iter = my_map.find(ele);
my_map.erase(iter); // erase传进去的是iterator
// find返回的是iterator
}
return true;
}
}
template<typename T>
MultiSet<T> MultiSet<T>::Union(const MultiSet& set) {
MultiSet<T> temp;
for (typename map<T, int>::iterator it = my_map.begin();
it != my_map.end(); ++it) {
for (int i = 0; i < it->second; ++i)
temp.insert(it->first);
}
for (typename map<T, int>::const_iterator it = set.my_map.begin();
it != set.my_map.end(); ++it) {
for (int i = 0; i < it->second; ++i)
temp.insert(it->first);
}
return temp;
}
template<typename T>
MultiSet<T> MultiSet<T>::Intersection(const MultiSet& set) {
MultiSet<int> temp;
typename map<T, int>::iterator it1 = my_map.begin();
// 注意用const_iterator否则编译错误
typename map<T, int>::const_iterator it2 = set.my_map.begin();
while (it1 != my_map.end() && it2 != set.my_map.end()) {
if (it1->first == it2->first) {
// 取小值
int min = (it1->second < it2->second ? it1->second : it2->second);
for (int j = 0; j < min; j++) {
temp.insert(it1->first);
}
it1++;
it2++;
} else if (it1->first < it2->first) {
// map中的元素会自动进行排序
it1++;
} else {
it2++;
}
}
return temp;
}
template<typename T>
ostream& operator<<(ostream& out, const MultiSet<T>& set) {
int number = set.my_map.size();
if (number == 0) {
out << "{}" << endl;
return out;
}
out << "{";
typename map<T, int>::const_iterator iter = set.my_map.begin();
for (int i = 0; i < set.my_map.size(); ++i) {
if (i == set.my_map.size() - 1) {
for (int j = 0; j < iter->second - 1; ++j) {
out << iter->first << ",";
}
out << iter->first << "}" << endl;
} else {
for (int j = 0; j < iter->second; ++j) {
out << iter->first << ",";
}
}
iter++;
}
return out;
}
下面是main函数部分
int main() {
MultiSet<int> set1;
int n, m;
cin >> n >> m;
for (int i = 0; i < n; i++) {
int k;
cin >> k;
set1.insert(k);
}
cout << set1;
MultiSet<int> set2 = set1;
cout << set2;
for (int i = 0; i < m; i++) {
int k;
cin >> k;
cout << set2.erase(k) << endl;
}
cout << set2;
cout << set1.Union(set2);
cout << set1.Intersection(set2);
cout << set2.Intersection(set1);
return 0;
}
很多函数map中已经实现,所以直接使用了, 一些操作符map也已经重载了,这使得整个实现过程简便了许多,也清晰了许多.
typename并不能创建新的类型名, 它只是通知编译器,将标识符解释为类型, 创建新的类型名可以使用关键字typedef