set
std::set<int> iset;
std::set<int>::iterator it = iset.insert(4).first;
(*it)++; // error. 原因:std::set的迭代器不能修改对应的元素.
//语法上不会报错,程序中也可以修改,但会破坏有序性,set可能表现出非预期的行为
这是因为:
std::set的特点是:
1. 对于插入、删除和查找操作,
set保证其时间复杂度都是O(log n);
2. set是一个有序的、可以前向和后向遍历的容器(双向迭代器);
3. set是一个元素类型和比较函数可以配置的容器,但是一经配置,就不可更改;
4. set的元素可以插入、删除,但是不可更改。
set在任何时刻都是一个有序的结构,而一旦破坏这个有序性,set可能表现出非预期的行为。为了保证set的概念完整性,C++STL厉
行规定了3和4两个限制,在绝大部分情况下,这两个限制是合理的。
2. set是一个有序的、可以前向和后向遍历的容器(双向迭代器);
3. set是一个元素类型和比较函数可以配置的容器,但是一经配置,就不可更改;
4. set的元素可以插入、删除,但是不可更改。
set在任何时刻都是一个有序的结构,而一旦破坏这个有序性,set可能表现出非预期的行为。为了保证set的概念完整性,C++STL厉
行规定了3和4两个限制,在绝大部分情况下,这两个限制是合理的。
但是,当我在set里面存的是shared_ptr元素时, 根本无所谓有没有序. 我就是要通过迭代器获取元素的非const引用. 解决如下:
#include <iostream>
#include <set>
template<class T>
inline T & GetStdSetElement(std::_Rb_tree_const_iterator<T> std_set_iterator)
{
return *(T *)&(*std_set_iterator);
}
int main()
{
using namespace std;
set<int> iset;
pair< set<int>::iterator, bool> res = iset.insert(4);
int & i = GetStdSetElement(res.first);
i++;
cout << *( iset.begin() ) << endl;
return 0;
}
/*
目的:学习set容器的使用
*程序输出:
6 5 4 3 2 1
4 already exists
1 2 3 4 5 6
1 element(s) removed
3 4 6
*coll2.erase(coll2.begin(), coll2.find(val));
*当coll2中不存在值等于val的元素时,会返回一个指向结尾的迭代器。
*此时,coll2.erase(coll2.begin(), coll2.find(val));会删除coll2中所有元素。
*/
#include <iostream>
#include <set>
using namespace std;
int main()
{
typedef set<int, greater<int> > IntSet; //只是构造时,创建了一个从大到小排列的容器,默认为从小到大。
// TEMPLATE CLASS set
/*
template<class _Kty,
class _Pr = less<_Kty>,
class _Alloc = allocator<_Kty> >
class set
: public _Tree<_Tset_traits<_Kty, _Pr, _Alloc, false> >
:*/
IntSet IntSetcoll;
IntSetcoll.insert(4);
IntSetcoll.insert(3);
IntSetcoll.insert(5);
IntSetcoll.insert(1);
IntSetcoll.insert(6);
IntSetcoll.insert(2);
IntSetcoll.insert(5);
set<int> setcoll; //默认为从小到大。
setcoll.insert(4);
setcoll.insert(3);
setcoll.insert(5);
setcoll.insert(1);
setcoll.insert(6);
setcoll.insert(2);
setcoll.insert(5);
IntSet::iterator pos;
for (pos = IntSetcoll.begin(); pos != IntSetcoll.end(); ++pos)
{
cout << *pos << ' ';
}
cout << endl;
pair<IntSet::iterator, bool> status = IntSetcoll.insert(4);
if (status.second)
{
cout << "4 inserted as element "
<< distance(IntSetcoll.begin(), status.first) + 1
<< endl;
}
else
{
cout << "4 already exists" << endl;
}
set<int> coll2(IntSetcoll.begin(), IntSetcoll.end());
copy(coll2.begin(), coll2.end(), ostream_iterator<int>(cout, " "));
cout << endl;
coll2.erase(coll2.begin(), coll2.find(3));
int num;
num = coll2.erase(5);
cout << num << " element(s) removed" << endl;
copy(coll2.begin(), coll2.end(), ostream_iterator<int>(cout, " "));
cout << endl;
getchar();
}
/*
目的:学习set容器的使用(二)
*程序输出:
coll1: 1 2 4 5 6 7
coll2: 7 6 5 4 2 1
coll1: 7 6 5 4 3 2 1
coll1 and coll2 have same sorting criterion
*RuntimeCmp(cmp_mode m = normal) : mode(m)
*不能改为RuntimeCmp() : mode(normal)
*带参数的构造函数,用来在程序运行中构造对象时传递参数
*/
//print.hpp头文件
#include <iostream>
/* PRINT_ELEMENTS()
*- print optional C-string optcstr followed by
*- all elements of the collection coll
*- separated by spaces
*/
template <class T>
inline void PRINT_ELEMENTS (const T& coll, const char* optcstr = "")
{
typename T::const_iterator pos;
std::cout << optcstr;
for (pos = coll.begin(); pos != coll.end(); ++pos)
{
std::cout << *pos << ' ';
}
std::cout << std::endl;
}
#include <iostream>
#include <set>
//#include "print.hpp"
using namespace std;
template <class T>
class RuntimeCmp
{
public:
enum cmp_mode {normal, reverse};
private:
cmp_mode mode;
public:
RuntimeCmp(cmp_mode m = normal) : mode(m)
{
}
bool operator() (const T &t1, const T &t2) const
{
return mode == normal ? t1 < t2 : t2 < t1;
}
bool operator== (const RuntimeCmp &rc)
{
return mode == rc.mode;
}
};
typedef set<int, RuntimeCmp<int> > IntSet; //一个类实例
void fill(IntSet &set); //stl的函数声明方式
int main()
{
IntSet coll1;
fill(coll1);
PRINT_ELEMENTS(coll1, "coll1: ");
RuntimeCmp<int> reverse_order(RuntimeCmp<int>::reverse);
IntSet coll2(reverse_order);
fill(coll2);
PRINT_ELEMENTS(coll2, "coll2: ");
coll1 = coll2;
coll1.insert(3);
PRINT_ELEMENTS(coll1, "coll1: ");
if (coll1.value_comp() == coll2.value_comp())
{
cout << "coll1 and coll2 have same sorting criterion" << endl;
}
else
{
cout << "coll1 and coll2 have different sorting criterion" << endl;
}
getchar();
}
void fill(IntSet &set)
{
set.insert(4);
set.insert(7);
set.insert(5);
set.insert(1);
set.insert(6);
set.insert(2);
set.insert(5);
}
map
/*
目的:学习map容器的使用。本事例运用Maps、Strings并于执行期指定排序准则事例程序
*程序输出:
Bestatter undertaker
Deutschland Germany
Haken snag
Hund dog
Unternehmen enterprise
arbeiten work
deutsch German
gehen walk
unternehmen undertake
arbeiten work
Bestatter undertaker
deutsch German
Deutschland Germany
gehen walk
Haken snag
Hund dog
Unternehmen undertake
*/
#include <iostream>
#include <iomanip>
#include <map>
#include <string>
#include <algorithm>
using namespace std;
/* function object to compare strings
* - allows you to set the comparison criterion at runtime
* - allows you to compare case insensitive
*/
class RuntimeStringCmp
{
public:
enum cmp_mode {normal, nocase};
private:
const cmp_mode mode;
static bool nocase_compare(char c1, char c2)
{
return toupper(c1) < toupper(c2);
}
public:
RuntimeStringCmp(cmp_mode m = normal) : mode(m)
{
}
bool operator() (const string &s1, const string &s2) const
{
if (mode == normal)
{
return s1 < s2;
}
else
{
return lexicographical_compare(s1.begin(), s1.end(), s2.begin(), s2.end(), nocase_compare);
}
}
};
/* container type
* - map with
* - string keys
* - string values
* - the special comparison object type
*/
typedef map<string, string, RuntimeStringCmp> StringStringMap;
//function that fills and prints such containers
void fillAndPrint(StringStringMap &coll); //stl的函数声明方式
int main()
{
//create a container with the default comparison criterion
StringStringMap coll1;
fillAndPrint(coll1);
//create an object
RuntimeStringCmp ignorecase(RuntimeStringCmp::nocase);
//create a container
StringStringMap coll2(ignorecase);
fillAndPrint(coll2);
getchar();
}
void fillAndPrint(StringStringMap &coll)
{
coll["Deutschland"] = "Germany";
coll["deutsch"] = "German";
coll["Haken"] = "snag";
coll["arbeiten"] = "work";
coll["Hund"] = "dog";
coll["gehen"] = "go";
coll["Unternehmen"] = "enterprise";
coll["unternehmen"] = "undertake";
coll["gehen"] = "walk";
coll["Bestatter"] = "undertaker";
//print
StringStringMap::iterator pos;
cout.setf(ios::left, ios::adjustfield);
for (pos = coll.begin(); pos != coll.end(); ++pos)
{
cout <<setw(15) << pos->first.c_str() << " " <<pos->second << endl;
}
cout << endl;
}