关联容器
set, multiset, map, multimap
- 内部元素有序排列,新元素插入的位置取决于它的值,查找速度快
- 除了个容器都有的函数外,还支持以下成员函数
成员函数 | 作用 |
---|---|
find | 查找等于某个元素的值(x小于y和y小于x同时不成立即为相等) |
lower_bound | 查找某个下界 |
upper_bound | 查找某个上届 |
equal_range | 同时查找上界和下界 |
count | 计算等于某个值得元素个数(x小于y和y小于x同时不成立即为相等) |
insert | 用以插入一个元素或一个区间 |
预备知识:pair
模板
template<class _T1, class _T2>
struct pair {
typedef _T1 first_type;
typedef _T2 second_type;
_T1 first;
_T2 second;
// 三种构造函数
pair(): first(), second() { } // 无参构造函数
pair(const _T1& __a, const _T2& __b) : first(__a), second(__b) { }
template<class _U1, class _U2>
pair(const pair<_U1, _U2>& __p) : first(__p.first), second(__p.second) { }
};
map/multimap
容器里放着的都是pair模版类的对象,且按first
从小到大排序。
第三个构造函数用法示例:
pair<int,int>
p(pair<double, double>(5.5, 4.6));
// p.first = 5, p.second = 4
multiset
template<class Key, class Pred = less<Key>, class A = allocator<Key> >
class multiset { …… };
- Pred类型的变量决定了multiset 中的元素“一个比另一个小”是怎么定义的。 multiset运行过程中,比较两个元素x,y的大小的做法,就是生成一个Pred类型的变量,假定为op,若表达式
op(x, y)
返回值为true,则x比y小。
Pred的缺省类型是less<Key
。 less
模板的定义:
template<class T>
struct less : public binary_function<T, T, bool> {
bool operator()(const T& x, const T& y) { return x < y; } const;
//less模板是靠 < 来比较大小的
};
multiset的成员函数
成员函数 | 作用 |
---|---|
iterator find (const T & val); | 在容器中查找值为val的元素,返回其迭代器。如果找不到,返回end() |
iterator insert (const T & val); | 将val插入到容器中并返回其迭代器 |
void insert ( iterator first, iterator last); | 将区间[first,last)插入容器 |
int count (const T & val); | 统计有多少个元素的值和val相等 |
iterator lower_bound (const T & val); | 查找一个最大的位置 it,使得[begin(), it) 中所有的元素都比 val 小 |
iterator upper_bound (const T & val); | 查找一个最小的位置 it,使得[it, end()) 中所有的元素都比 val 大 |
pair<iterator, iterator> equal_range (const T & val); | 同时求得lower_bound和upper_bound |
iterator erase (iterator it); | 删除it指向的元素,返回其后面的元素的迭代器(Visual studio 2010上如此,但是在 C++标准和Dev C++中,返回值不是这样) |
multiset的用法
#include <set>
using namespace std;
class A { };
int main() {
multiset<A> a;
a.insert(A()); // error
}
multiset <A> a;
就等价于multiset<A, less<A>> a;
插入元素时,multiset会将被插入元素和已 有元素进行比较。由于less模板是用 < 进行 比较的,所以,这都要求 A 的对象能用 < 比较,即适当重载了 <。
#### multiset用法示例
#include <set>
#include <iostream>
using namespace std;
template <class T>
void Print(T first, T last) {
for (; first != last; ++first)
cout << *first << " ";
cout << endl;
}
class A {
private:
int n;
public:
A(int n_) {
n = n_;
}
friend bool operator < (const A & a1, const A & a2) {
return a1.n < a2.n;
}
friend ostream & operator << (ostream & o, const A & a2) {
o << a2.n;
return o;
}
friend class MyLess;
};
class MyLess {
public:
bool operator()(const A & a1, const A & a2) { // 按各位数比较大小
return (a1.n % 10) < (a2.n % 10);
}
};
int main() {
const int SIZE = 6;
A a[SIZE] = {4, 22, 19, 8, 33, 40};
multiset<A> m1; // m1用"<"比较大小
m1.insert(a, a+SIZE);
m1.insert(22);
cout << "1) " << m1.count(22) << endl; // 输出 1) 2
cout << "2) "; Print(m1.begin(), m1.end()); // 输出 2) 4 8 19 22 22 33 40
multiset<A>::iterator pp = m1.find(19);
if (pp != m1.end()) // 条件为真说明找到
cout << "found" << endl; //本行会被执行,输出 found
cout << "3) "; cout << * m1.lower_bound(22) << ","
<< * m1.upper_bound(22) << endl; // 输出 3) 22,33
pp = m1.erase(m1.lower_bound(22), m1.upper_bound(22)); // pp指向被删元素的下一个元素
cout << "4) "; Print(m1.begin(), m1.end()); //输出 4) 4 8 19 33 40
cout << "5) "; cout << * pp << endl; //输出 5) 33
multiset<A, MyLess> m2; // m2用MyLess::operator()比较大小
m2.insert(a, a+SIZE);
cout << "6) "; Print(m2.begin(), m2.end()); // 输出 6) 40 22 33 4 8 19
return 0;
}
set
template<class Key, class Pred = less<Key>,
class A = allocator<Key> >
class set { … }
// 插入set中已有的元素时,忽略插入。
set用法示例
#include <iostream>
#include <set>
using namespace std;
int main() {
typedef set<int>::iterator IT;
int a[5] = {3, 4, 6, 1, 2};
set<int> st(a, a+5); // st里是 1 2 3 4 6
pair<IT, bool> result;
result = st.insert(5); // st变成 1 2 3 4 5 6
if( result.second ) // 插入成功则输出被插入元素
cout << *result.first << " inserted" << endl; // 输出: 5 inserted
if( st.insert(5).second )
cout << *result.first << " already exists" << endl; // 输出 5 already exists
else
cout << *result.first << endl;
pair<IT, IT> bounds = st.equal_range(4);
cout << *bounds.first << "," << *bounds.second << endl; // 输出:4,5
return 0;
}