欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C++ STL中的set容器

程序员文章站 2024-03-22 17:54:58
...

set/multiset容器的基本概念

    1.set容器的基本概念

     set的特性是,所有元素都会根据元素的键值自动被排序,set的元素不像map那样可以同时拥有实值和键值,set元素即是键值也是实值。set不允许两个元素有相同的键值。
     那可以通过set的迭代器改变set元素的值吗?答案是不行的,因为set元素值就是其键值,关系到set元素的额排序规则,如果任意改变set元素值,会严重破坏set结构。换句话说,set的iterator是一种const_iterator。
     set拥有和list某些相同的性质,当对容器中的元素进行插入或者删除操作的时候,操作之前的迭代器,在操作完成之后依然有效,被删除的那个元素的迭代器必然是个例外。

    2.multiset容器的基本概念

     multiset特性及用法和set完全相同,唯一的差别在于它允许键值重复,set和multiset的底层实现都是红黑树,是平衡二叉树的一种。

    3.set的一些用法

      3.1 插入操作

可以看到插入的数据是无序的

void printset(set<int>&s) { //写一个自己的打印set函数,方便后续使用
	for (set<int>::iterator it = s.begin(); it != s.end(); it++) {
		cout << *it << endl;
	}
}
void test_set() {
	set<int>s;
	s.insert(35);//插入数据用inset
	s.insert(25);
	s.insert(1);
	s.insert(27);
	s.insert(26);
	printset(s);
}
int main() {
	test_set();
	return 0;
}

C++ STL中的set容器
但输出结果是有序的,set会自动将输入排序,这点和Python的 不一样。

      3.2 删除操作

void test_set() {
	set<int>s;
	s.insert(35);//插入数据用inset
	s.insert(25);
	s.insert(1);
	s.insert(27);
	s.insert(26);
	printset(s);
	cout << endl;
	s.erase(1);
	printset(s);
}

C++ STL中的set容器

      3.3 查找操作

void test_set2() {
	set<int>s;
	s.insert(35);//插入数据用inset
	s.insert(25);
	s.insert(1);
	s.insert(27);
	s.insert(26);
	//s.find(35);//查找set s中有么有35;若该元素存在则返回该元素的迭代器,否则返回ste.end()
	set<int>::iterator pos = s.find(35); //写一个迭代器
	if (pos != s.end()) {
		cout << "该元素存在" <<*pos<< endl;
	}
	else cout << "不存在" << endl;

	int num = s.count(24); //统计某个元素的个数,结果只可能是0或者1
	cout << num << endl;
}

C++ STL中的set容器

      3.3 lower_bound的用法

lower_bound(key_elem);//返回第一个key>=keyelem元素的迭代器

void test_set3() {
	set<int>s;
	s.insert(35);//插入数据用inset
	s.insert(25);
	s.insert(1);
	set<int>::iterator res = s.lower_bound(30);
	if (res != s.end()) {
		cout << "存在大于该数的数据是" << *res << endl;
	}
	else cout << "不存在" << endl;
}

C++ STL中的set容器
跟find操作很像,都是返回一个迭代器或者找不到则是容器的尾部迭代器。

      3.5 equal_range的用法

equal_range(keyelem)返回容器中key与keyelem相等的上下限的两个迭代器,返回的其实就是lower_bound和upper_bound,通过一个api可以同时找到这两个值。

void test_set3() {
	set<int>s;
	s.insert(35);//插入数据用inset
	s.insert(25);
	s.insert(1);
	set<int>::iterator res = s.lower_bound(30);
	if (res != s.end()) {
		cout << "存在大于该数的数据是" << *res << endl;
	}
	else cout << "不存在" << endl;

	set<int>::iterator res1 = s.upper_bound(30);
	if (res1 != s.end()) {
		cout << "存在大于该数的数据是" << *res1 << endl;
	}
	else cout << "不存在" << endl;

	pair< set<int>::iterator, set<int>::iterator > it = s.equal_range(30);
	if (it.first != s.end()) {
		cout << "找到了lower_bound的值" << *(it.first) << endl;
	}
	if (it.second != s.end()) {
		cout << "找到了upper_bound的值" << *(it.second) << endl;
	}
}

      3.6 pair的用法

void test_set4() {
	pair<string, int> p(string("tom"), 18);
	cout << "name is :" << p.first << " " << "age is: " << p.second << endl;
}

C++ STL中的set容器

      3.7 更改set默认排序方法

set默认从小到大排序,虽然说set插入之后就不能更改了,但在插入之前是可以更改的。

void test_set2() {
	set<int,mycompare>s;
	s.insert(35);//插入数据用inset
	s.insert(25);
	s.insert(1);
	s.insert(27);
	s.insert(26);
	for (set<int, mycompare>::iterator mt = s.begin(); mt != s.end(); mt++) {
		cout << *mt << endl;
	}

C++ STL中的set容器

      3.8 用set去重

void test_set35() {//用set实现对vector去重的功能
	set<int>s;
	vector<int>v;
	v.push_back(1);
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	for (vector<int>::iterator it1 = v.begin(); it1 != v.end(); it1++) {
		s.insert(*it1);
	}
	for (set<int>::iterator it2 = s.begin(); it2 != s.end(); it2++) {
		cout << *it2 << endl;
	}
}

    4.multiset的一些用法

其他属性都差不多,主要是multiset可以插入重复数值

void test_set5() {
	multiset<int>ms;
	ms.insert(10);
	ms.insert(10);
	for (multiset<int>::iterator mt = ms.begin(); mt != ms.end(); mt++) {
		cout << *mt << endl;
	}
}

C++ STL中的set容器

    5.set中自定义数据类型的用法

class person_set { //定义一个类
public:
	person_set(string name, int age) {
		this->m_name = name;
		this->m_age = age;
	}
	string m_name;
	int m_age;
};

class mycompareperson { //自定义排序类型
public:
	bool operator()(const person_set&p1, const person_set&p2) {
		return p1.m_age < p2.m_age;
	}
};
void test_set24() {
	set<person_set,mycompareperson>s;
	person_set p1("aaa", 10); //实例化
	person_set p2("bbb", 30);
	person_set p3("ccc", 20);
	person_set p4("ddd", 50);
	person_set p5("eee", 40);
	s.insert(p1);
	s.insert(p2);
	s.insert(p3);
	s.insert(p4);
	s.insert(p5);
	//对于自定义数据类型,需要指定排序规则

	for (set<person_set>::iterator pt = s.begin(); pt != s.end(); pt++) {
		cout <<"name is:"<< (*pt).m_name <<"    "<<"the age is :"<< (*pt).m_age << endl;
	}
}

C++ STL中的set容器
set中可以使用自定义数据 类型,但前提一定得先指定排序类型,不然会报错,也就是代码中的mycompareperson