C++ STL容器详解

news2025/1/16 21:49:22

string容器

string的基本概念

本质

string是C++风格的字符串,而string本质上是一个类

string与char* 的区别

char * 是一个指针

string是一个类,类内部封装了char*,管理这个字符串,是一个char*型的容器。

string的构造函数

构造函数

string();                                 //创建一个空的字符串 例如: string s;

string s1; //创建空字符串,调用无参构造函数

string(const char* s);         //使用字符串s初始化

const char* str = "hello world";
string s2(str); //把c_string转换成了string

string(const string& str); //使用一个string对象初始化另一个string对象

string s2 = "KKGG";
string s3(s2);  //调用拷贝构造函数

string(int n, char c);        //使用n个字符c初始化

string str(5, 'a'); //aaaaa

string的基本操作

1、string字符串的赋值操作

string& operator=(const char* s); //char*类型字符串 赋值给当前的字符串

string str1;
str1 = "kk";

string& operator=(const string &s); //把字符串s赋给当前的字符串

string str1 = "gg";
string str2;
str2 = str1;

string& operator=(char c); //字符赋值给当前的字符串

string str3;
str3 = 'KG';

string& assign(const char *s); //把字符串s赋给当前的字符串

string str4;
str4.assign("hello, this is my world");

string& assign(const char *s, int n); //把字符串s的前n个字符赋给当前的字符串

string str5;
str5.assign("hello c++",5);  //str5 = "hello"

string& assign(const string &s); //把字符串s赋给当前字符串

string str6;
str6.assign(str5);

string& assign(int n, char c); //用n个字符c赋给当前字符串

string str7;
str7.assign(5, 'k'); //str7 = "kkkkk"

2、string字符串的拼接

string& operator+=(const char* str); //重载+=操作符

string& operator+=(const string& str); //重载+=操作符

string str1 = "我喜欢";
str1 += "写博客";  
//str1 = "我喜欢写博客"

string& operator+=(const char c); //重载+=操作符

string str1 = "我喜欢";
string str2 = "写博客";  
str1 += str2;
//str1 = "我喜欢写博客"

string& append(const char *s); //把字符串s连接到当前字符串结尾

string str = "I";
str.append(" love");
//str = "I love"

string& append(const char *s, int n); //把字符串s的前n个字符连接到当前字符串结尾

string str = "I ";
str.append("love myself",4);
//str = "I love"

string& append(const string &s); //同operator+=(const string& str)

string s1 = "kk";
string s2 = "gg";
s1.append(s2);
//s1 = "kkgg"

string& append(const string &s, int pos, int n);//字符串s中从pos开始的n个字符连接到字符串结尾

string str1;
string str2 = "abcdefg";
str1.append(str2, 4, 3);  //efg
//从下标4位置开始 ,截取3个字符,拼接到字符串末尾

3、string字符串的查找和替换

int find(const string& str, int pos); //查找str第一次出现位置,从pos开始查找

int find(const char* s, int pos); //查找s第一次出现位置,从pos开始查找

int find(const char* s, int pos, int n); //从pos位置查找s的前n个字符第一次位置

int find(const char c, int pos); //查找字符c第一次出现位置

void test(){
	//查找
	string str1 = "abcdefgde";

	int pos = str1.find("de");

	if (pos == -1){
		cout << "未找到" << endl;
	}
	else{
		cout << "pos = " << pos << endl;
	}
}

int rfind(const string& str, int pos); //查找str最后一次位置,从pos开始查找

int rfind(const char* s, int pos); //查找s最后一次出现位置,从pos开始查找

int rfind(const char* s, int pos, int n); //从pos查找s的前n个字符最后一次位置

int rfind(const char c, int pos); //查找字符c最后一次出现位置

void test(){
	//查找
    string str1 = "abcdefgde";
	int pos = str1.rfind("de");

	cout << "pos = " << pos << endl;
    //pos = 7
}

string& replace(int pos, int n, const string& str); //替换从pos开始n个字符为字符串str

string& replace(int pos, int n,const char* s); //替换从pos开始的n个字符为字符串s

void test(){
	//替换
	string str1 = "abcdefgde";
	str1.replace(1, 3, "1111");

	cout << "str1 = " << str1 << endl;
    //str1 = "a1111efgde"
}

4、string字符串的比较

int compare(const string &s) const; //与字符串s比较

int compare(const char *s) const; //与字符串s比较

void test(){

	string s1 = "hello";
	string s2 = "aello";

	int ret = s1.compare(s2); //字符串比较

	if (ret == 0) {
		cout << "s1 等于 s2" << endl;
	}
	else if (ret > 0){
		cout << "s1 大于 s2" << endl;
	}
	else{
		cout << "s1 小于 s2" << endl;
	}
}

5、string字符串的存取

char& operator[](int n); //通过[]方式取字符

char& at(int n); //通过at方法获取字符

void test(){
	string str = "hello world";

	for (int i = 0; i < str.size(); i++){
		cout << str[i] << " ";
	}
	cout << endl;

	for (int i = 0; i < str.size(); i++){
		cout << str.at(i) << " ";
	}
	cout << endl;

	//字符修改
	str[0] = 'x';
	str.at(1) = 'x';
	cout << str << endl;
}

6、string字符串的插入和删除

总结:插入和删除的起始下标都是从0开始

string& insert(int pos, const char* s); //插入字符串string& insert(int pos, const string& str); //插入字符串

string& insert(int pos, int n, char c); //在指定位置插入n个字符c

//字符串插入
void test(){
	string str = "hello";
	str.insert(1, "***");
	cout << str << endl;
    //str = "h***ello"
}

string& erase(int pos, int n = npos); //删除从Pos开始的n个字符

//字符串删除
void test(){
	string str = "hello";

	str.erase(1, 3);  
    //从1号位置开始3个字符
	cout << str << endl;
    //str = "ho"
}

7、string字符串的子串

string substr(int pos, int n); //返回由pos开始的n个字符组成的字符串

//子串
void test(){

	string str = "abcdefg";
	string subStr = str.substr(1, 3);

	cout << "subStr = " << subStr << endl;
    //subStr = "bcd";
}

vector容器

vector的基本概念

1、vector数据结构和数组非常相似,也称为单端数组

2、不同之处在于数组是静态空间,而vector可以动态扩展

vector的构造函数

构造函数

vector<T> v; //采用模板实现类实现,默认构造函数

vector<int> v; //无参构造

vector(v.begin(), v.end()); //将v[begin(), end())区间中的元素拷贝给本身

void test(){
	vector<int> v1; 
	for (int i = 0; i < 10; i++){
		v1.push_back(i);
	}
	vector<int> v2(v1.begin(), v1.end());
}

vector(n, elem); //构造函数将n个elem拷贝给本身

vector<int> v(10, 100);

vector(const vector &vec); //拷贝构造函数

vector<int> v3(10, 100);
vector<int> v4(v3);

vector的基本操作

vector赋值操作

vector& operator=(const vector &vec);//重载等号操作符

void test(){
	vector<int> v1; //无参构造
	for (int i = 0; i < 10; i++){
		v1.push_back(i);
	}
	vector<int>v2;
	v2 = v1;
}

assign(beg, end); //将[beg, end)区间中的数据拷贝赋值给本身

assign(n, elem); //将n个elem拷贝赋值给本身

vector<int>v3;
v3.assign(v1.begin(), v1.end());
	
vector<int>v4;
v4.assign(10, 100);

vector容量和大小

empty(); //判断容器是否为空

capacity(); //容器的容量

size(); //返回容器中元素的个数

void test(){
	vector<int> v1;
	for (int i = 0; i < 10; i++){
		v1.push_back(i);
	}
	
	if (v1.empty()){
		cout << "v1为空" << endl;
	}
	else{
		cout << "v1不为空" << endl;
		cout << "v1的容量 = " << v1.capacity() << endl;
		cout << "v1的大小 = " << v1.size() << endl;
	}
    //v1不为空
    //v1的容量 = 13
    //v1的大小 = 10
}

resize(int num); //重新指定容器的长度为num,若容器变长,则以默认值填充新位置。

                                //如果容器变短,则末尾超出容器长度的元素被删除。

resize(int n,elem);//重新指定容器长度为n,若容器变长,则以elem值填充新位置。

                                    //如果容器变短,则末尾超出容器长度的元素被删除

vector插入和删除

push_back(ele); //尾部插入元素ele

pop_back(); //删除最后一个元素

insert(const_iterator pos, ele); //迭代器指向位置pos插入元素ele

insert(const_iterator pos, int count,ele);//迭代器指向位置pos插入count个元素ele

erase(const_iterator pos); //删除迭代器指向的元素

erase(const_iterator start, const_iterator end);//删除迭代器从start到end之间的元素

clear(); //删除容器中所有元素

//插入和删除
void test(){
	vector<int> v1;
	//尾插
	v1.push_back(10);
	v1.push_back(20);
	v1.push_back(30);
	v1.push_back(40);
	v1.push_back(50);

	//尾删
	v1.pop_back();

	//插入
	v1.insert(v1.begin(), 100);
	v1.insert(v1.begin(), 2, 1000);

	//删除
	v1.erase(v1.begin());

	//清空
	v1.erase(v1.begin(), v1.end());
	v1.clear();
}

vector数据存取

at(int idx); //返回索引idx所指的数据

operator[]; //返回索引idx所指的数据

front(); //返回容器中第一个数据元素

back(); //返回容器中最后一个数据元素

void test(){
	vector<int>v1;
	for (int i = 0; i < 10; i++){
		v1.push_back(i);
	}

	for (int i = 0; i < v1.size(); i++){
		cout << v1[i] << " ";
	}
	cout << endl;

	for (int i = 0; i < v1.size(); i++){
		cout << v1.at(i) << " ";
	}
	cout << endl;


	cout << "v1的第一个元素为: " << v1.front() << endl;
	cout << "v1的最后一个元素为: " << v1.back() << endl;
}

vector互换容器

swap(vec); // 将vec与本身的元素互换

v1.swap(v2);

vector预留空间

reserve(int len);//容器预留len个元素长度,预留位置不初始化,元素不可访问

vector<int> v;
v.reserve(100000);//预留空间

deque容器

deque的基本概念

双端数组,可以对头端进行插入删除操作。

deque与vector的区别

(1)vector对于头部的插入删除效率低,数据量越大,效率越低

(2)deque相对而言,对头部的插入删除速度回比vector快

(3)vector访问元素时的速度会比deque快,这和两者内部实现有关

deque的构造函数

构造函数

deque<T>; //默认构造形式

deque(beg, end); //构造函数将[beg, end)区间中的元素拷贝给本身

deque(n, elem); //构造函数将n个elem拷贝给本身

deque(const deque &deq); //拷贝构造函数

//deque构造
void test{

	deque<int> d1; //无参构造函数
	for (int i = 0; i < 10; i++){
		d1.push_back(i);
	}

	deque<int> d2(d1.begin(),d1.end());

	deque<int>d3(10,100);

	deque<int>d4 = d3;
}

deque的基本操作

deque赋值操作

deque& operator=(const deque &deq); //重载等号操作符

assign(beg, end); //将[beg, end)区间中的数据拷贝赋值给本身

assign(n, elem); //将n个elem拷贝赋值给本身

//赋值操作
void test(){
	deque<int> d1;
	for (int i = 0; i < 10; i++){
		d1.push_back(i);
	}
    //d1 = 0 1 2 3 4 5 6 7 8 9
	deque<int>d2;
	d2 = d1;
    //d2 = 0 1 2 3 4 5 6 7 8 9
	deque<int>d3;
	d3.assign(d1.begin(), d1.end());
    //d3 = 0 1 2 3 4 5 6 7 8 9
	deque<int>d4;
	d4.assign(5, 100);
    //d4 = 100 100 100 100 100
}

deque大小操作

deque.empty(); //判断容器是否为空

deque.size();   //返回容器中元素的个数

deque.resize(num); //重新指定容器的长度为num,若容器变长,则以默认值填充新位置。

                                   //如果容器变短,则末尾超出容器长度的元素被删除。

deque.resize(num, elem); //重新指定容器的长度为num,若容器变长,则以elem值填充新位置。                                   //如果容器变短,则末尾超出容器长度的元素被删除。

注意:deque没有容量的概念

void test(){
	deque<int> d1;
	for (int i = 0; i < 10; i++){
		d1.push_back(i);
	}

	//判断容器是否为空
	if (d1.empty()) {
		cout << "d1为空!" << endl;
	}
	else {
		cout << "d1不为空!" << endl;
		//统计大小
		cout << "d1的大小为:" << d1.size() << endl;
	}

	//重新指定大小
	d1.resize(15, 1);//多余的部分用1填充

	d1.resize(5);
}

deque插入和删除

两端插入操作:

push_back(elem); //在容器尾部添加一个数据

push_front(elem); //在容器头部插入一个数据

pop_back(); //删除容器最后一个数据

pop_front(); //删除容器第一个数据

void test(){
	deque<int> d;
	//尾插
	d.push_back(10);
	d.push_back(20); //10 20

	//头插
	d.push_front(100);
	d.push_front(200); //200 100 10 20

	//尾删
	d.pop_back(); //200 100 10

	//头删
	d.pop_front();//100 10
}

 指定位置操作

insert(pos,elem); //在pos位置插入一个elem元素的拷贝,返回新数据的位置

insert(pos,n,elem); //在pos位置插入n个elem数据,无返回值

insert(pos,beg,end); //在pos位置插入[beg,end)区间的数据,无返回值

void test(){
	deque<int> d;
	d.push_back(10);
	d.push_back(20);
	d.push_front(1);
	d.push_front(2);
    //2 1 10 20

	d.insert(d.begin(), 100);
    //100 2 1 10 20

	d.insert(d.begin(), 2,1000);
    //1000 1000 100 2 1 10 20
}

clear(); //清空容器的所有数据

erase(beg,end); //删除[beg,end)区间的数据,返回下一个数据的位置

erase(pos); //删除pos位置的数据,返回下一个数据的位置

//删除
void test03(){
	deque<int> d;
	d.push_back(10);
	d.push_back(20);
	d.push_front(1);
	d.push_front(2);
    //2 1 10 20

	d.erase(d.begin());
     //1 10 20

	d.erase(d.begin(), d.end());
    //

	d.clear();
    //
}

deque数据存取

at(int idx); //返回索引idx所指的数据

operator[]; //返回索引idx所指的数据

front(); //返回容器中第一个数据元素

back(); //返回容器中最后一个数据元素

void test(){
	deque<int> d;
	d.push_back(10);
	d.push_back(20);
	d.push_front(1);
	d.push_front(2);

	for (int i = 0; i < d.size(); i++) {
		cout << d[i] << " ";//2 1 10 20
	}
	cout << endl;

	for (int i = 0; i < d.size(); i++) {
		cout << d.at(i) << " ";//2 1 10 20
	}
	cout << endl;

	cout << "front:" << d.front() << endl;
    //2
	cout << "back:" << d.back() << endl;
    //20

}

deque排序

sort(iterator beg, iterator end) //对beg和end区间内元素进行排序

void test{
	deque<int> d;
	d.push_back(10);
	d.push_back(20);
	d.push_front(1);
	d.push_front(2);

	sort(d.begin(), d.end());
    //1 2 10 20
}

stack容器

stack的基本概念

概念:stack是一种先进后出(或后进先出)的数据结构,它只有一个出口。

stack的构造函数

stack<T> stk; //stack采用模板类实现, stack对象的默认构造形式

stack(const stack &stk); //拷贝构造函数

stack的基本操作

赋值操作:

stack& operator=(const stack &stk); //重载等号操作符

数据存取:

push(elem); //向栈顶添加元素

pop(); //从栈顶移除第一个元素

top(); //返回栈顶元素

大小操作:

empty(); //判断堆栈是否为空

size(); //返回栈的大小

void test(){
	//创建栈容器 栈容器必须符合先进后出
	stack<int> s;

	//向栈中添加元素,叫做 压栈 入栈
	s.push(10);
	s.push(20);
	s.push(30);

	while (!s.empty()) {
		//输出栈顶元素
		cout << s.top() << endl; //30
		//弹出栈顶元素
		s.pop();
	}
	cout << "栈的大小为:" << s.size() << endl;//2
}

queue容器

queue的基本概念

概念:队列是一种先进先出的数据结构,它有两个出口。

队列容器允许从一端新增元素,从另一端移除元素。

队列中只有队头和队尾才可以被外界使用,因此队列不允许有遍历行。

queue的构造函数

queue<T> q; //queue采用模板类实现,queue对象的默认构造形式

queue(const queue &que); //拷贝构造函数

queue的基本操作

赋值操作:

queue& operator=(const queue &que); //重载等号操作符

数据存取:

push(elem); //往队尾添加元素

pop(); //从队头移除第一个元素

back(); //返回最后一个元素

front(); //返回第一个元素

大小操作:

empty(); //判断堆栈是否为空

size(); //返回栈的大小

list容器

list的基本概念

链表(list)是一种物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的。

链表的组成:链表由一系列结点组成。

结点的组成:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。

list的构造函数

构造函数

list<T> li; //list采用采用模板类实现,对象的默认构造形式

list(beg,end); //构造函数将[beg, end)区间中的元素拷贝给本身

list(n,elem); //构造函数将n个elem拷贝给本身

list(const list &li); //拷贝构造函数

void test(){
	list<int>L1;
	L1.push_back(10);
	L1.push_back(20);
	L1.push_back(30);
	L1.push_back(40);

	list<int>L2(L1.begin(),L1.end());

	list<int>L3(L2);

	list<int>L4(10, 1000);
}

list的基本操作

list赋值和交换

assign(beg, end); //将[beg, end)区间中的数据拷贝赋值给本身

assign(n, elem); //将n个elem拷贝赋值给本身

list& operator=(const list &lst); //重载等号操作符

//赋值
void test(){
	list<int>L1;
	L1.push_back(10);
	L1.push_back(20);
	L1.push_back(30);
	L1.push_back(40);

	//赋值
	list<int>L2;
	L2 = L1;

	list<int>L3;
	L3.assign(L2.begin(), L2.end());


	list<int>L4;
	L4.assign(10, 100);
}

swap(lst); //将lst与本身的元素互换

//交换
void test(){

	list<int>L1;
	L1.push_back(10);
	L1.push_back(20);
	L1.push_back(30);
	L1.push_back(40);

	list<int>L2;
	L2.assign(4, 1);
    //L1 =10 20 30 40
    //L2 = 1 1 1 1

	L1.swap(L2);
    //L1 = 1 1 1 1
    //L2 =10 20 30 40

}

list大小操作

size(); //返回容器中元素的个数

empty(); //判断容器是否为空

resize(num); //重新指定容器的长度为num,若容器变长,则以默认值填充新位置

                        //如果容器变短,则末尾超出容器长度的元素被删除

resize(num, elem); //重新指定容器的长度为num,若容器变长,则以elem值填充新位置

​                                 //如果容器变短,则末尾超出容器长度的元素被删除

//大小操作
void test(){
	list<int>L1;
	L1.push_back(10);
	L1.push_back(20);
	L1.push_back(30);
	L1.push_back(40);

	if (L1.empty()){
		cout << "L1为空" << endl;
	}
	else{
		cout << "L1不为空" << endl;
		cout << "L1的大小为: " << L1.size() << endl;//4
	}

	//重新指定大小
	L1.resize(10);

	L1.resize(2);
}

list插入和删除

push_back(elem);//在容器尾部加入一个元素

pop_back();//删除容器中最后一个元素

push_front(elem);//在容器开头插入一个元素

pop_front();//从容器开头移除第一个元素

insert(pos,elem);//在pos位置插elem元素的拷贝,返回新数据的位置。

insert(pos,n,elem);//在pos位置插入n个elem数据,无返回值。

insert(pos,beg,end);//在pos位置插入[beg,end)区间的数据,无返回值。

clear();//移除容器的所有数据

erase(beg,end);//删除[beg,end)区间的数据,返回下一个数据的位置。

erase(pos);//删除pos位置的数据,返回下一个数据的位置。

remove(elem);//删除容器中所有与elem值匹配的元素。

void test(){
	list<int> L;
	//尾插
	L.push_back(10);
	L.push_back(20);
	L.push_back(30);
	//头插
	L.push_front(100);
	L.push_front(200);
	L.push_front(300);


	//尾删
	L.pop_back();
	//头删
	L.pop_front();

	//插入
	list<int>::iterator it = L.begin();
	L.insert(++it, 1000);

	//删除
	it = L.begin();
	L.erase(++it);

	//移除
	L.push_back(10000);
	L.push_back(10000);
	L.push_back(10000);
	L.remove(10000);
    
    //清空
	L.clear();
}

list数据存取

front(); //返回第一个元素

back(); //返回最后一个元素

//数据存取
void test(){
	list<int>L1;
	L1.push_back(10);
	L1.push_back(20);
	L1.push_back(30);
	L1.push_back(40);

	
	//cout << L1.at(0) << endl;//错误 不支持at访问数据
	//cout << L1[0] << endl; //错误  不支持[]方式访问数据
	cout << "第一个元素为: " << L1.front() << endl;
	cout << "最后一个元素为: " << L1.back() << endl;

	//list容器的迭代器是双向迭代器,不支持随机访问
	list<int>::iterator it = L1.begin();
	//it = it + 1;//错误,不可以跳跃访问,即使是+1
}

list反转和排序

reverse(); //反转链表

sort(); //链表排序

//反转和排序
void test(){
	list<int> L;
	L.push_back(90);
	L.push_back(30);
	L.push_back(20);
	L.push_back(70);
    //90 30 20 70

	//反转容器的元素
	L.reverse();
    //70 20 30 90

	//排序
	L.sort(); //默认的排序规则 从小到大
	//20 30 70 90

	L.sort(greater<int>()); //指定规则,从大到小
	//90 70 30 20
}

例题:创建一个链表,实现前n个数的旋转。

例如:1 2 3 4 5 6,实现前3个数的旋转变成4 5 6 1 2 3

int main(){
	list<int> li;

	li.push_back(10);
	li.push_back(20);
	li.push_back(30);
	li.push_back(40);
	li.push_back(50);  //初始化5个数据

	int n = 0;
	cin >> n;  //选择翻转几个数

	list<int>::iterator it = li.begin();
	for (int i = 0; i < n; i++){  //使用迭代器遍历到翻转的位置
		it++;
	}
	
	reverse(li.begin(),it);       //逆置前 n 个数
	reverse(it, li.end());        //逆置后 li.size() - n 个数
	reverse(li.begin(), li.end());//整体逆置

	return 0;
}

set/multiset容器

set的基本概念

所有元素都会在插入时自动被排序

set/multiset属于关联式容器,底层结构是用二叉树实现。

set和multiset区别

(1)set不允许容器中有重复的元素。

(2)multiset允许容器中有重复的元素。

set的构造函数

构造函数

set<T> st; //默认构造函数

set(const set &st); //拷贝构造函数

//构造和赋值
void test(){
	set<int> s1;

	s1.insert(10);
	s1.insert(30);
	s1.insert(20);
	s1.insert(40);

	//拷贝构造
	set<int>s2(s1);

	//赋值
	set<int>s3;
	s3 = s2;
}

set的基本操作

set大小和交换

size(); //返回容器中元素的数目

empty(); //判断容器是否为空

swap(st); //交换两个集合容器

void test(){

	set<int> s1;

	s1.insert(10);
	s1.insert(30);
	s1.insert(20);
	s1.insert(40);

	if (s1.empty()){
		cout << "s1为空" << endl;
	}
	else{
		cout << "s1不为空" << endl;
		cout << "s1的大小为: " << s1.size() << endl;//4
	}

    set<int> s2;
	s2.insert(100);
	s2.insert(300);
	s2.insert(200);
	s2.insert(400);

	s1.swap(s2);
}

set插入和删除

insert(elem); //在容器中插入元素。

clear(); //清除所有元素。

erase(pos); //删除pos迭代器所指的元素,返回下一个元素的迭代器。

erase(beg, end); //删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。

erase(elem); //删除容器中值为elem的元素。

//插入和删除
void test(){
	set<int> s1;
	//插入
	s1.insert(10);
	s1.insert(30);
	s1.insert(20);
	s1.insert(40);
	printSet(s1);

	//删除
	s1.erase(s1.begin());

	s1.erase(30);

	//清空
	//s1.erase(s1.begin(), s1.end());
	s1.clear();
}

set查找和统计

find(key); //查找key是否存在,若存在,返回该键的元素的迭代器;

                                                  若不存在,返回set.end();

count(key); //统计key的元素个数


//查找和统计
void test(){
	set<int> s1;
	//插入
	s1.insert(10);
	s1.insert(30);
	s1.insert(20);
	s1.insert(40);
	
	//查找
	set<int>::iterator pos = s1.find(30);

	if (pos != s1.end()){
		cout << "找到了元素 : " << *pos << endl;
	}
	else{
		cout << "未找到元素" << endl;
	}

	//统计
	int num = s1.count(30);
	cout << "num = " << num << endl;
}

set和multiset的区别

set不可以插入重复数据,而multiset可以。

set插入数据的同时会返回插入结果,表示插入是否成功。

multiset不会检测数据,因此可以插入重复数据。

//set和multiset区别
void test(){
	set<int> s;
	pair<set<int>::iterator, bool>  ret = s.insert(10);
	if (ret.second) {
		cout << "第一次插入成功!" << endl;
	}
	else {
		cout << "第一次插入失败!" << endl;
	}

	ret = s.insert(10);
	if (ret.second) {
		cout << "第二次插入成功!" << endl;
	}
	else {
		cout << "第二次插入失败!" << endl;
	}
    
	//multiset
	multiset<int> ms;
	ms.insert(10);
	ms.insert(10);

	for (multiset<int>::iterator it = ms.begin(); it != ms.end(); it++) {
		cout << *it << " ";
	}
}

set容器排序

主要技术点:利用仿函数,可以改变排序规则。

class MyCompare 
{
public:
	bool operator()(int v1, int v2) {
		return v1 > v2;
	}
};
void test(){    
	set<int> s1;
	s1.insert(10);
	s1.insert(40);
	s1.insert(20);
	s1.insert(30);
	s1.insert(50);

	//默认从小到大
	for (set<int>::iterator it = s1.begin(); it != s1.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;

	//指定排序规则
	set<int,MyCompare> s2;
	s2.insert(10);
	s2.insert(40);
	s2.insert(20);
	s2.insert(30);
	s2.insert(50);

	for (set<int, MyCompare>::iterator it = s2.begin(); it != s2.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;
}

pair队组创建

pair<type, type> p (value1, value2);

pair<type, type> p = make_pair(value1, value2);

//对组创建
void test(){
	pair<string, int> p(string("Tom"), 20);
	cout << "姓名: " <<  p.first << " 年龄: " << p.second << endl;

	pair<string, int> p2 = make_pair("Jerry", 10);
	cout << "姓名: " << p2.first << " 年龄: " << p2.second << endl;
}

map/multimap容器

map的基本概念

map中所有元素都是pair。

pair中第一个元素为key(键值),起到索引作用,第二个元素为value(实值)。

所有元素都会根据元素的键值自动排序。

本质:map/multimap属于关联式容器,底层结构是用二叉树实现。

map和multimap区别:

(1)map不允许容器中有重复key值元素

(2)multimap允许容器中有重复key值元素

map的构造函数

map<T1, T2> mp; //map默认构造函数

map(const map &mp); //拷贝构造函数

map& operator=(const map &mp); //重载等号操作符

void test(){
	map<int,int>m; //默认构造
	m.insert(pair<int, int>(1, 10));
	m.insert(pair<int, int>(2, 20));
	m.insert(pair<int, int>(3, 30));

	map<int, int>m2(m); //拷贝构造

	map<int, int>m3;
	m3 = m2; //赋值
}

map的基本操作

map大小和交换

size(); //返回容器中元素的数目

empty(); //判断容器是否为空

swap(st); //交换两个集合容器

//交换
void test(){
	map<int, int>m;
	m.insert(pair<int, int>(1, 10));
	m.insert(pair<int, int>(2, 20));
	m.insert(pair<int, int>(3, 30));

	map<int, int>m2;
	m2.insert(pair<int, int>(4, 100));
	m2.insert(pair<int, int>(5, 200));
	m2.insert(pair<int, int>(6, 300));

	m.swap(m2);
}

map插入和删除

insert(elem); //在容器中插入元素

clear(); //清除所有元素

erase(pos); //删除pos迭代器所指的元素,返回下一个元素的迭代器

erase(beg, end); //删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器

erase(key); //删除容器中值为key的元素

void test(){
	//插入
	map<int, int> m;
	//第一种插入方式
	m.insert(pair<int, int>(1, 10));
	//第二种插入方式
	m.insert(make_pair(2, 20));
	//第三种插入方式
	m.insert(map<int, int>::value_type(3, 30));
	//第四种插入方式
	m[4] = 40; 

	//删除
	m.erase(m.begin());
	m.erase(3);//删除key为3


	//清空
	m.erase(m.begin(),m.end());
	m.clear();
}

map查找和统计

find(key); //查找key是否存在,若存在,返回该键的元素的迭代器

                                                  若不存在,返回set.end()

count(key); //统计key的元素个数

//查找和统计
void test(){
	map<int, int>m; 
	m.insert(pair<int, int>(1, 10));
	m.insert(pair<int, int>(2, 20));
	m.insert(pair<int, int>(3, 30));

	//查找
	map<int, int>::iterator pos = m.find(3);

	if (pos != m.end()){
		cout << "找到了元素 key = " << (*pos).first << " value = " << (*pos).second << endl;
	}
	else{
		cout << "未找到元素" << endl;
	}

	//统计
	int num = m.count(3);
	cout << "num = " << num << endl;
}

map容器排序

利用仿函数可以指定map容器的排序规则。

对于自定义数据类型,map必须要指定排序规则,同set容器。

class MyCompare {
public:
	bool operator()(int v1, int v2) {
		return v1 > v2;
	}
};

void test() {
	//默认从小到大排序
	//利用仿函数实现从大到小排序
	map<int, int, MyCompare> m;

	m.insert(make_pair(1, 10));
	m.insert(make_pair(2, 20));
	m.insert(make_pair(3, 30));
	m.insert(make_pair(4, 40));
	m.insert(make_pair(5, 50));

	for (map<int, int, MyCompare>::iterator it = m.begin(); it != m.end(); it++) {
		cout << "key:" << it->first << " value:" << it->second << endl;
	}
}

 例题:随机输入n个数,找到所有出现重复的数。

例如:输入2,3,1,0,2,5,3  输出2,3

int test(){
	multimap<int,int> m;

	int n = 0;
	cin >> n;

	for (int i = 0; i < n; i++){
		int t = 0;
		cin >> t;
		m.insert(pair<int, int>(t, m.count(t) + 1));
	}

	for (multimap<int, int>::iterator it = m.begin(); it != m.end(); it++){
		if (m.count(it->second) > 1){
			cout << it->first << " ";
		}
	}
}

其他内容推荐:

c语言字符函数详细介绍

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1398678.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据库性能优化的解决方案

目录​​​​​​​ 1、什么是数据库性能优化 1.1 数据库性能优化的概念 1.2 为何需要进行数据库性能优化 1.3 数据库性能优化的好处 2、数据库性能优化的基本原理 2.1 数据库查询优化 2.2 数据库索引优化 2.3 数据库表结构优化 2.4 数据库硬件优化 3、数据库查询优化…

机床导轨误差对机械加工品质的影响

机床导轨是确定机床各部件相对位置关系的基准&#xff0c;也是相对运动的基准&#xff0c;其精度直接决定了机械加工产品的精度&#xff0c;机床导轨要确保精准,才能保证机械加工产品的良好&#xff0c;否则&#xff0c;会影响加工品质&#xff0c;主要体现在以下几方面&#x…

力扣刷MySQL-第六弹(详细讲解)

&#x1f389;欢迎您来到我的MySQL基础复习专栏 ☆* o(≧▽≦)o *☆哈喽~我是小小恶斯法克&#x1f379; ✨博客主页&#xff1a;小小恶斯法克的博客 &#x1f388;该系列文章专栏&#xff1a;力扣刷题讲解-MySQL &#x1f379;文章作者技术和水平很有限&#xff0c;如果文中出…

C++——函数的定义

1&#xff0c;概述 作用&#xff1a;将一段经常使用的代码封装起来&#xff0c;减少重复代码 一个较大的程序&#xff0c;一般分为若干个程序块&#xff0c;每个模块实现特定的功能。 2&#xff0c;函数的定义 函数的定义一般主要有五个步骤&#xff1a; 1&#xff0c;返回…

C++ 学习系列 -- std::function 与 std::bind

一 std::function 与 std::bind 的介绍 1. std::function std::function 是 c 11 的新特性 &#xff0c;包含在头文件<functional>中&#xff0c;为了更方便的调用函数而引入。 std::function 是一个函数包装器&#xff08;function wrapper&#xff09;&#xff0c;…

英国金融时报关注TRX登陆Mercado Bitcoin交易所:波场TRON强化南美洲布局,国际化进程持续加速

近日,波场TRON网络原生代币TRX正式上线巴西最大的合规加密交易所Mercado Bitcoin。英国金融时报、Decrypt、Blockworks等财经及加密行业权威媒体对该话题进行了报道,表示此次合作是波场TRON全球业务增长的有力证明,也表明该平台力求处于数字经济前沿的坚定决心。 据悉,Mercado…

小白快速上手maven【基础篇】

Maven的概念和作用 Maven是什么&#xff1f;POM的概念 Maven的作用&#xff1f; 提供自动化构建项目的方式&#xff0c;并且统一了项目的结构管理项目中的依赖 Maven基础概念-仓库&#xff0c;坐标&#xff0c;仓库配置 仓库&#xff1a;用于存储各种jar包资源 根据功能的不…

【微信小程序开发】环境介绍和基本使用

文章目录 前言1. 项目的基本组成结构1.1 JSON 配置文件的作用1.2 如何新建小程序页面1.3 修改项目首页1.4 WXML 模板1.5 WXSS 样式1.6 JS 逻辑交互 2. 宿主环境2.1 什么是宿主环境2.2 通信模型2.3 运行机制2.4 组件2.4.1 view 组件的基本使用&#xff1a;2.4.2 scroll-view 组件…

专业137总分439东南大学920专业基础综合考研经验电子信息与通信电路系统芯片

我本科是南京信息工程大学&#xff0c;今年报考东南大学信息学院&#xff0c;成功逆袭&#xff0c;专业137&#xff0c;政治69&#xff0c;英语86&#xff0c;数一147&#xff0c;总分439。以下总结了自己的复习心得和经验&#xff0c;希望对大家复习有一点帮助。啰嗦一句&…

OpenAI CEO称“AGI时代”即将来临,下一个风口或为能源领域

原创 | 文 BFT机器人 在最近的达沃斯论坛上&#xff0c;Sam Altman以其深邃的见解和前瞻性的思考&#xff0c;再次成为了全场关注的焦点。他以一场激情四溢的演讲&#xff0c;深入剖析了人工智能技术的未来发展趋势&#xff0c;以及它可能对社会和工作领域产生的深远影响。 Al…

HTTP 协议和 TCP/IP 协议之间有什么区别?

HTTP&#xff08;超文本传输协议&#xff09;和TCP/IP&#xff08;传输控制协议/互联网协议&#xff09;是两种在互联网通信中广泛使用的协议&#xff0c;它们之间的区别和联系对许多人来说可能还不是很清晰&#xff0c;今天我们就带大家来一起了解一下HTTP和TCP/IP协议这2者之…

JAVAEE初阶 封装与分用

封装和分用 一.封装1.1 应用层1.2 传输层1.3 网络层1.4 数据链路层1.5 物理层 二.分用2.1 物理层2.2 数据链路层2.3 网络层2.4 传输层2.5 应用层 三. 交换机的封装分用四.路由器的封装分用五. 网络中数据传输的单位 在讲解封装与分用前&#xff0c;我们需要先说明一个例子。 例…

【Qt】ubuntu环境下使用命令行安装Qt

起因是我上一篇文章说的&#xff0c;官网下的安装包卡死在第一步安装界面了。 于是我就问GPT有没有纯命令行的安装方式&#xff0c;果然是有的。 在Ubuntu上安装Qt可以使用以下命令&#xff1a; 1. 首先&#xff0c;添加Qt的官方存储库到系统中&#xff1a; sudo add-apt-rep…

如何进行产品的人机交互设计?

产品的人机交互设计是指通过用户界面和用户体验设计来优化产品与用户之间的交互过程&#xff0c;从而提高产品的易用性、可用性和用户满意度。人机交互设计需要考虑用户的需求、行为模式、心理感受以及技术实现&#xff0c;下面我将介绍如何进行产品的人机交互设计。 首先&…

汇川PLC如何连接电脑进行数据通信和远程上下载

准备工作 一台可联网操作的电脑一台单网口的远程透传网关及博达远程透传配置工具网线一条&#xff0c;用于实现网络连接和连接PLC一台汇川PLC及其编程软件InoPrShop一张4G卡或WIFI天线实现通讯(使用4G联网则插入4G SIM卡&#xff0c;WIFI联网则将WIFI天线插入USB口&#xff09…

国科大模式识别与机器学习2015-2019、2021、2023仅考题

2015 &#xff08;8&#xff09;试描述线性判别函数的基本概念&#xff0c;并说明既然有线性判别函&#xff0c;为什么还需要非线性判别函数&#xff1f;假设有两种模式&#xff0c;每类包括6个4维不同的模式&#xff0c;且良好分布。如果他们是线性可分的。问权向量至少需要几…

phpmyadmin 创建服务器

phpmyadmin默认的服务器是localhost 访问setup&#xff0c;创建新的服务器 添加服务器信息 点击应用&#xff0c;服务器创建成功 下载配置文件config.inc.php&#xff0c;放到WWW目录下 可再次访问setup&#xff0c;发现已配置过了 访问登录页面&#xff0c;发现可选…

Python利用Excel读取和存储测试数据完成接口自动化教程

http_request2.py用于发起http请求 #读取多条测试用例#1、导入requests模块import requests#从 class_12_19.do_excel1导入read_data函数from do_excel2 import read_datafrom do_excel2 import write_datafrom do_excel2 import count_case#定义http请求函数COOKIENonedef ht…

Linux 查看时区及修改时区的方法

查看时区 ll /etc/localtime可以看到这里显示的是纽约的时区 修改时区 timedatectl set-timezone Asia/Shanghai如图所示&#xff0c;表示修改成功为上海时区

zookeeper window 安装

下载 Apache ZooKeeper 解压Zookeeper安装包到指定目录&#xff0c;注意目录不要有空格。 备份zoo_sample.cfg并改名zoo.cfg 注意&#xff1a;此处的路径一定要使用双斜杠" \\ " D:\\apache-zookeeper-3.8.3-bin\\data 新建环境变量&#xff1a;ZOOKEEPER_HOME D…