一、关联容器
关联容器有set,multiset,map,multimap
特点:内部元素有序排列,新元素插入位置取决于它的值
在说明关联容器前,需要先介绍以下pair模板,因为map,multimap容器里存放的都是pair模板类对象。
#include <iostream>
using namespace std;
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){ }
};
Pari模板提供了三种构造方法,这里提供了三种构造pair的方式,其中注意下第三种构造方法:
pair<int, int> p(pair<double, double>(5.5,4.6));
cout << p.first << p.second;
二、multiset和set
1.multiset
multiset类实现代码较复杂,这里了解下模板的定义:
template<class Key, class Pred = less<Key>, class A = allocator<Key>>
这里的Pred变量决定multiset中的元素以何种方式“一个比另一个小”是如何定义的,其缺省类型为less<Key>
less的模板定义:
template<class T>
struct less : public binary_function<T, T, bool>
{
bool operator()(const T & x, const T & y) const
{
return x < y;
}
};
下面自己编写less函数:
struct MyLess{
bool operator ()(const A & a1, const A & a2)
{
return (a1.n % 10) < (a2.n % 10);
}
};
通过MyLess函数生成multimap
#include <iostream>
#include <set>
using namespace std;
class A{
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 & a1){ o << a1.n; return o; }
friend class MyLess;
private:
int n;
};
template <class T>
void Print(T first, T second)
{
for(; first != second; ++first)
cout << * first << " ";
cout << endl;
}
struct MyLess{
bool operator ()(const A & a1, const A & a2)
{
return (a1.n % 10) < (a2.n % 10);
}
};
int main()
{
double a[] = {11,27,3,51,36};
multiset<A, MyLess> m1;
m1.insert(a, a + 5);
Print(m1.begin(), m1.end());
return 0;
}
multiset常用的成员函数有
1.iterator insert(const T & val); 将val插入到容器中并返回其迭代器。
multiset<A> m1;
multiset<A>::iterator pp = m1.insert(5);
cout << * pp;
2.void insert( iterator first,iterator last); 将区间[first,last)插入容器。
double a[] = {11,27,3,51,36};
multiset<A> m1;
m1.insert(a, a + 5);
Print(m1.begin(), m1.end());
3.iterator find(const T & val); 在容器中查找值为val的元素,返回其迭代器。如果找不到,返回end()
double a[] = {11,27,3,51,36};
multiset<A> m1;
m1.insert(a, a + 5);
if (m1.find(3) != m1.end())
cout << "found" << endl;
4.int count(const T & val); 统计有多少个元素的值和val相等。
5.iterator lower_bound(const T & val); 查找一个最大的位置 it,使得[begin(),it) 中所有的元素都比 val 小
6.iterator upper_bound(const T & val); 查找一个最小的位置 it,使得[it,end()) 中所有的元素都比 val
7.pair<iterator,iterator> equal_range(const T & val); 同时求得lower_bound和upper_bound
8.iterator erase(iterator it); 删除it指向的元素,返回其后面的元素的迭代器(Visual studio 2010上如此,但是在 C++标准和Dev C++中,返回值不是这样)。
A a[6] = {4, 22, 19, 8, 33, 40};
multiset<A> m1;
m1.insert(a, a + 6);
m1.erase(m1.lower_bound(7),m1.upper_bound(32));
Print(m1.begin(), m1.end());
三、map和multimap
1.multimap的函数部分如下所示:
template<class Key, class T, class Pred = less<Key>, class A = allocator<T>>
class multimap{
...
typedef pair<const Key, T> value_type;
...
}
这里的Key代表关键字类型,multimap中的元素由<关键字,值>构成,每个元素又是一个pair对象。在multimap中允许多个元素的关键字相同。
2.multimap示例:
#include <iostream>
#include <map>
using namespace std;
int main()
{
typedef multimap<int, double, less<int> > mmid;
mmid pairs;
cout << pairs.count(15) << endl;
pairs.insert(mmid::value_type(15, 2.7));
pairs.insert(mmid::value_type(15,99.3));
cout << pairs.count(15) << endl;
pairs.insert(mmid::value_type(30,111.11));
pairs.insert(mmid::value_type(10,22.22));
pairs.insert(mmid::value_type(25,33.333));
pairs.insert(mmid::value_type(20,9.3));
for(mmid::const_iterator i = pairs.begin(); i != pairs.end();++i)
cout << i->first << "," << i->second << endl;
}
3.map
template<class Key, class T, class Pred = less<Key>, class A = allocator<T> >
class map{
...
typedef pair <const Key, T> value_type;
...
}
map中的元素都是pair模板类对象。关键字(first成员变量)各不相同
下述语句例如:
map<int, double> pairs;
pairs[50] = 5;
如果存在关键字为50的元素,则修改其值为5,若不存在,则插入此元素
4.map示例
#include <iostream>
#include <map>
using namespace std;
template <class Key, class Value>
ostream & operator << (ostream & o, const pair<Key, Value> & p)
{
o << "(" << p.first << "," << p.second << ")";
return o;
}
int main()
{
typedef map<int, double, less<int> > mmid;
mmid pairs;
cout << pairs.count(15) << endl;
pairs.insert(mmid::value_type(15,2.7));
// make_pair生成一个pair对象
pairs.insert(make_pair(15,99.3));
cout << pairs.count(15) << endl;
pairs.insert(mmid::value_type(20,9.3));
mmid::iterator i;
for(i = pairs.begin(); i != pairs.end(); ++i)
cout << *i << " ";
cout << endl;
// 若没有key=40元素,则插入
int n = pairs[40];
for(i = pairs.begin(); i != pairs.end(); ++i)
cout << *i << " ";
cout << endl;
pairs[15] = 6.28;
for(i = pairs.begin(); i != pairs.end(); ++i)
cout << *i << " ";
cout << endl;
return 0;
}
四、容器适配器
1.stack
stack是后进先出的数据结构,只能插入、删除、访问栈顶元素。
可以通过vector,list,deque实现,默认deque,一般来说用vector和deque相对于用list性能较好
template<class T, class Cont = deque<T> >
其操作有:push,pop,top
2.queue
与stack基本类似:
template<class T, class Cont = deque<T> >
注意这里push发生在队尾,pop,top发生在队头。先进先出,同时还有back成员函数返回队尾元素的引用。
3.priority_queue
和queue基本类似,priority_queue 通常用堆排序技术实现,保证最大的元素总是 在最前面。即执行pop操作时,删除的是最大的元素;执行top 操作时,返回的是最大元素的常引用。默认的元素比较器是 less<T>
template <class T, class Container = vector<T>, class Compare = less<T> >
4.示例
#include <queue>
#include <iostream>
using namespace std;
int main()
{
priority_queue<double> pq1;
pq1.push(3.2);
pq1.push(9.8);
pq1.push(5.4);
while(!pq1.empty())
{
cout << pq1.top() << " ";
pq1.pop();
}
cout << endl;
priority_queue<double, vector<double>, greater<double> > pq2;
pq2.push(3.2);
pq2.push(9.8);
pq2.push(9.8);
pq2.push(5.4);
while( !pq2.empty())
{
cout << pq2.top() << " ";
pq2.pop();
}
return 0;
}
这里的empty用于判断适配器是否为空,同时还有size()返回适配器中元素个数。
参考:
《C++ Primer》第五版
郭炜老师的《C++面向对象程序设计》