MultiSet(借用map实现multiset的功能)

很不错的题, 有助于理解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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值