标准模版库学习之关联式容器

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两个限制,在绝大部分情况下,这两个限制是合理的。
 
但是,当我在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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值