C++ STL容器详解

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语言字符函数详细介绍

  • 24
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我会一直在的

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值