第八节 常用容器

1 string容器

1.1 string基本概念

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

string和char *的区别:

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

特点:

string内部封装了很多成员

例如:查找find,拷贝copy,删除delete替换replace,插入insert

string管理char *所分配的内存,不用担心复制越界和取值越界等,由类内部进行负责

1.2 string构造函数

构造函数原型:

string();                         //创建一个空的字符串,例如:string str;
string(const char* s);             //使用字符串初始化
string(const string& str);        //使用一个string对象初始化另一个string对象
string(int n,char c);            //使用n个字符初始化
#include<iostream>
#include<string>
/*
string();                          //创建一个空的字符串,例如:string str;
string(const char* s);              //使用字符串初始化
string(const string& str);         //使用一个string对象初始化另一个string对象
string(int n,char c);             //使用n个字符初始化
*/

using namespace std;

void test01()
{
	//string是一个类
	//我们前期用的一直都是string类的默认构造,也就是下面的方式
	//默认构造初始化
	string str1;		

	//使用字符串初始化
	const char* str = "hello,world";
	string s2(str);				//有参构造进行初始化
	cout << s2 << endl;

	string s3(s2);				//拷贝构造进行初始化
	cout << s3 << endl;

	string s4(5, 'a');			//使用n个字符初始化
	cout << s4 << endl;
}

int main()
{
	test01();
	system("pause");
	return 0;
}

1.3 string赋值操作

功能描述:给string字符串进行赋值

赋值函数的原型:

string& operator=(const char* s)           //char*类型字符串赋值给当前字符串
string& operator=(const string &s)         //把字符串s赋值给当前字符串
string& operator=(const c)                 //字符赋值给当前字符串
string& assign(const char* s)              //把字符串s赋值给当前字符串
string& assign(const char* s,int n)       //把字符串s的前n个字符赋值给字符串
string& assign(const string  &s)           //把字符串s赋值给当前字符串
string& assign(int n,char c)               //用n个字符c赋值给字符串
#include<iostream>
#include<string>

/*
string& operator=(const char* s)       	   //char*类型字符串赋值给当前字符串
string& operator=(const string &s)     	   //把字符串s赋值给当前字符串
string& operator=(const c)                  //字符赋值给当前字符串
string& assign(const char* s)           	  //把字符串s赋值给当前字符串
string& assign(const char* s,int n)   	  //把字符串s的前n个字符赋值给字符串
string& assign(const string  &s)            //把字符串s赋值给当前字符串
string& assign(int n,char c)                //用n个字符c赋值给字符串
*/


using namespace std;

void test01()
{
	string str1;
	str1 = "hello world";
	cout << str1 <<endl;

	string str2;
	str2 = str1;
	cout << str2 << endl;

	string str3;
	str3 = 'c';
	cout << str3 << endl;

	string str4;
	str4.assign("hello world");
	cout << str4 << endl;

	string str5;
	str5.assign("hello world",5);
	cout << str5 << endl;

	string str6;
	str6.assign(str5);
	cout << str6 << endl;

	string str7;
	str7.assign(5,'c');
	cout << str7 << endl;
}

int main()
{
	test01();
	system("pause");
	return 0;
}

1.4 string字符串拼接

功能描述:实现字符串末尾拼接字符串

函数原型:

string&  operator+=(const char* str)            //重载+=操作符
string&  operator+=(const char c)               //重载+=操作符
string&  operator+=(const string& str)          //重载+=操作符
string&  append(const char* s)                  //把字符串s连接到当前字符串结尾
string&  append(const char* s,int n)           //把字符串s的前n个字符连接到当前字符串结尾
string&  append(const string& s)                //同operator+=(const string& str)
string&  append(const string& s,int pos,int n)  //把字符串s从pos开始的n个字符连接到字符串尾部
#include<iostream>
#include<string>

using namespace std;

//字符串拼接
/*
string&  operator+=(const char* str)                //重载+=操作符
string&  operator+=(const char c)                   //重载+=操作符
string&  operator+=(const string& str)              //重载+=操作符
string&  append(const char* s)                      //把字符串s连接到当前字符串结尾
string&  append(const char* s,int n)               //把字符串s的前n个字符连接到当前字符串结尾
string&  append(const string& s)                    //同operator+=(const string& str)
string&  append(const string& s,int pos,int n)      //把字符串s从pos开始的n个字符连接到字符串尾部
*/


void test01()
{
	string str1 = "我";
	str1 += "爱玩游戏";
	cout << str1 << endl;

	str1 += ":";
	cout << str1 << endl;

	string str2 = "LOL DNF";
	str1 += str2;
	cout << str1 << endl;

	string str3 = "I";
	str3.append("Love");
	cout << str3 << endl;

	str3.append("Game 666",4);
	cout << str3 << endl;

	str3.append(str2);
	cout << str3 << endl;

	str3.append(str2, 0, 3);		//只截取LOL
	cout << str3 << endl;
	str3.append(str2, 4, 3);		//只截取LOL
	cout << str3 << endl;
}

int main()
{
	test01();
	system("pause");
	return 0;
}

1.5 string查找和替换

功能描述:【查找:查找指定字符串是否存在】【替换:在指定的位置替换字符串】

函数原型:

int find(const string& str,int pos = 0) const;    //查找str第一次出现位置,从pos开始查找
int find(const char* s,int pos = 0) const;        //查找s第一次出现位置,从pos开始查找
int find(const char* s,int pos = 0,int n) const;  //从pos位置查找s的前n个字符第一次位置
int find(const char c,int pos = 0) const;          //查找字符c第一次出现位置
int rfind(const string& str,int pos = npos) const;  //查找str最后一次出现位置,从pos开始查找
int rfind(const char* s,int pos = npos) const;    //查找s最后一次出现位置,从pos开始查找
int rfind(const char* s,int pos ,int n) const;     //从pos查找s的前n个字符最后一次位置
int rfind(const char c,int pos = 0) const;        //查找字符c最后一次出现位置
string& replace(int pos,int n ,const string& str) //替换从pos开始n个字符为字符串str
string& replace(int pos,int n,const char* s)      //替换从pos开始的n个字符为字符串s
#include<iostream>
#include<string>

using namespace std;
//查找
void test01()
{
	string str = "abcdefgde";
	int pos = str.find("de");
	if (pos == -1)
	{
		cout << "未查到字符串:" << pos << endl;
	}
	else
	{
		cout << "查到字符串:" << pos << endl;
	}

	//rfind和find的区别,find从左到右查,rfind从右向左查(从右查到的第一个,就是从左到右的最后一个)
	pos = str.rfind("de");
	if (pos == -1)
	{
		cout << "未查到字符串:" << pos << endl;
	}
	else
	{
		cout << "查到字符串:" << pos << endl;
	}
}

//替换
void test02()
{
	string str = "abcdefg";
	str.replace(1, 3, "1111");
	cout << str << endl;
}

int main()
{
	test01();
	test02();
	system("pause");
	return 0;
}

总结:

  • find查找是从往右,rfind是从右往左
  • find找到字符串后返回查找的第一个字符位置,找不到返回-1
  • replace在替换时,要指定从那个位置起,多少个字符,替换成什么样的字符串

1.6 string字符串比较

功能描述:字符串之间比较

比较方式:字符串比较是按字符的ASCII码进行对比

=     返回    0

>     返回    1

<     返回     -1

函数原型:

int compare(const string &s) const;        //与字符串s比较
int compare(const char *s) const;          //与字符串s比较
#include<iostream>
#include<string>

using namespace std;
//查找
void test01()
{
	string str1 = "hello";
	//string str2 = "hello";

	const char* str2 = "hello";

	if (str1.compare(str2) == 0)
	{
		cout << "str1等于ste2" << endl;
	}
	else if (str1.compare(str2) > 0)
	{
		cout << "str1大于ste2" << endl;
	}
	else
	{
		cout << "str1小于ste2" << endl;
	}

}

int main()
{
	test01();

	system("pause");
	return 0;
}

1.7 string字符存取

string中单个字符存取方式有两种

char& operator[](int  n)           //通过[]方式取字符
char& at(int  n)                   //通过at方式取字符
#include<iostream>
#include<string>

using namespace std;
//查找
void test01()
{
	string str1 = "hello";
	cout << "str1 = " << str1 << endl;

	//1,通过[]获取单个字符
	for (int i = 0; i < str1.size(); i++)
	{
		cout << str1[i] << " ";
	}
	cout << endl;

	//1,通过at获取单个字符
	for (int i = 0; i < str1.size(); i++)
	{
		cout << str1.at(i) << " ";
	}
	cout << endl;

	//修改单个字符
	str1[0] = 'x';
	cout << "str1 = " << str1 << endl;

	str1.at(1) = 'x';
	cout << "str1 = " << str1 << endl;
}

int main()
{
	test01();

	system("pause");
	return 0;
}

 1.8 string插入和删除

功能描述:对string字符串进行插入和删除字符操作

函数原型:

string& insert(int pos,const char* s);      //插入字符串
string& insert(int pos,const string& str);  //插入字符串
string& insert(int pos,int n,char c);       //在指定位置插入n个字符c
string& erase(int pos,int n = npos);       //删除从pos开始的n个字符
#include<iostream>
#include<string>

using namespace std;
//查找
void test01()
{
	string str1 = "hello";
	//字符串插入
	str1.insert(1, "111");
	cout << str1 << endl;

	//字符串删除
	str1.erase(1, 3);
	cout << str1 << endl;
}

int main()
{
	test01();

	system("pause");
	return 0;
}

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

1.9 string子串

功能描述:从字符串获取想要的子串

函数原型

string& substr(int pos = 0,int n = npos) const; //返回由pos开始的n个字符组成的字符串
#include<iostream>
#include<string>

using namespace std;

void test01()
{
	//string子串
	string str = "abcdef";
	string subStr = str.substr(1, 3);
	cout << subStr << endl;
}

//实用操作
void test02()
{
	string str = "jackie@qq.com";
	//从邮箱名中截取用户名	标志性@前面就是名字
	int pos = str.find("@");
	string subStr = str.substr(0, pos);
	cout << subStr << endl;
}

int main()
{
	test01();
	test02();

	system("pause");
	return 0;
}

2 vector容器

2.1 vector基本概念

功能:vector数据结构和数组非常相似,也称为单端数组

vector与普通数组的区别:不同之处在于数组是静态空间,而vector可以动态扩展

动态扩展:并不是在原空间之后续接新空间,而是找更大的内存空间,然后将原数据拷贝到新空间,释放原空间

2.2 vector构造函数

功能描述:创建vector容器并初始化

函数原型:

vector<T> v;                    //采用模板实现类实现,默认构造函数
vector(v.begin(),v.end());      //将v[begin(),end()]区间的元素拷贝给自身
vector(n, elem)                 //构造函数将n个elem拷贝给自身
vector(const vector &vec)       //拷贝构造函数
#include<iostream>
#include<string>
#include<vector>

using namespace std;
//打印接口
void printVector(vector<int>& v1)
{
	for (vector<int>::iterator it = v1.begin(); it != v1.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}


void test01()
{
	vector<int> v1;				   //默认构造
	for (int i = 1; i < 10;i++)		
	{
		v1.push_back(i);			//插入数据
	}
	printVector(v1);

	vector<int> v2(v1.begin(), v1.end());	//将v1区间的元素拷贝给v2
	printVector(v2);

	vector<int> v3(10,100);						//将10个100拷贝给v3
	printVector(v3);

	vector<int> v4(v3);					//拷贝构造
	printVector(v4);
}


int main()
{
	test01();

	system("pause");
	return 0;
}

2.3 vector赋值操作

功能描述:给vector容器进行赋值

函数原型:

vector& operator=(const vector &vec)    //重载等号操作符
assign(beg,end);                       //将[beg,end]区间中的数据拷贝赋值给本身
assign(n,elem);                        //将n个elem拷贝赋值给本身
#include<iostream>
#include<string>
#include<vector>

using namespace std;
//打印接口
void printVector(vector<int>& v1)
{
	for (vector<int>::iterator it = v1.begin(); it != v1.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}


void test01()
{
	vector<int> v1;				   
	for (int i = 1; i < 10;i++)		
	{
		v1.push_back(i);			
	}
	printVector(v1);

	//赋值操作  operator=
	vector<int> v2;
	v2 = v1;
	printVector(v2);

	//区间赋值
	vector<int> v3;
	v3.assign(v2.begin(),v2.end());
	printVector(v3);

	//将n个elem赋值给容器
	vector<int> v4;
	v4.assign(10, 100);
	printVector(v4);
}


int main()
{
	test01();

	system("pause");
	return 0;
}

2.4 vector容量和大小

功能描述:对vector容器的容量和大小操作

函数原型:

empty();                //判断函数是否为空
capacity();             //容器的容量
size();                 //返回容器中元素的个数
resize(int num);        //重新指定容器的长度为num,若容器变长,则以默认值填充新位置
                        //如果容器变短,则末尾超出容器长度的元素被删除
resize(int num,elem)    //重新指定容器的长度为num,若容器变长,则以elem值填充新位置
                        //如果容器变短,则末尾超出容器长度的元素被删除
#include<iostream>
#include<string>
#include<vector>

using namespace std;
//打印接口
void printVector(vector<int>& v1)
{
	for (vector<int>::iterator it = v1.begin(); it != v1.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}


void test01()
{
	vector<int> v1;				   
	for (int i = 1; i < 10;i++)		
	{
		v1.push_back(i);			
	}
	printVector(v1);

	if (v1.empty() == true)
	{
		cout << "v1为空" << endl;
	}
	else
	{
		cout << "v1不为空" << endl;
		cout << "v1的容量:" << v1.capacity() << endl;
		cout << "v1的大小:" << v1.size() << endl;
	}
	//增加容器的大小
	v1.resize(11, 100);		//利用重载版本,可以指定默认的填充值,参数2
	printVector(v1);		//如果比原来长了,那么默认的填充值为0
	
	//减小容器的大小
	v1.resize(5);			//如果比原来短了,那么会舍弃后面的值,size变小,但是capacity不变
	printVector(v1);

}


int main()
{
	test01();

	system("pause");
	return 0;
}

2.5 vector插入与删除

功能描述:对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();                                          //删除容器中所有的元素
#include<iostream>
#include<string>
#include<vector>

using namespace std;
//打印接口
void printVector(vector<int>& v1)
{
	for (vector<int>::iterator it = v1.begin(); it != v1.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}


void test01()
{
	vector<int> v1;

	//尾插
	v1.push_back(10);
	v1.push_back(20);
	v1.push_back(30);
	printVector(v1);

	//尾删
	v1.pop_back();
	printVector(v1);

	//插入指定位置的元素	第一个参数迭代器
	v1.insert(v1.begin()+1,100);
	printVector(v1);

	//插入多个
	v1.insert(v1.begin() + 1,2,1000);
	printVector(v1);

	//删除指定位置的元素
	v1.erase(v1.begin() + 3);
	printVector(v1);

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

}


int main()
{
	test01();

	system("pause");
	return 0;
}

总结:

  • 尾插 --- push_back
  • 尾删 --- pop_back
  • 插入 --- insert (位置迭代器)
  • 删除 --- erase (位置迭代器)
  • 清空 --- clear

2.6 vector数据存取

功能描述:对vector中的数据存取操作

函数原型:

at(int idx);      //返回索引id所指的数据
operator[];       //返回索引idx所指的数据
front();          //返回容器中第一个数据元素
back();           //返回容器中最后一个数据元素
#include<iostream>
#include<string>
#include<vector>

using namespace std;


void test01()
{
	vector<int> v1;

	//尾插
	v1.push_back(10);
	v1.push_back(20);
	v1.push_back(30);

	//1,利用迭代器访问容器里面的元素
	for (vector<int>::iterator it = v1.begin(); it != v1.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;

	//2,利用[]访问容器里面的元素
	for (int i = 0; i < v1.size(); i++)
	{
		cout << v1[i] << " ";
	}
	cout << endl;

	//3,利用at函数访问容器中的元素
	for (int j = 0; j < v1.size(); j++)
	{
		cout << v1.at(j) << " ";
	}
	cout << endl;

	//获取容器中的第一个元素
	cout << "第一个元素为:" << v1.front() << endl;
	//获取容器中的最后一个元素
	cout << "最后一个元素为:" << v1.back() << endl;
}

int main()
{
	test01();

	system("pause");
	return 0;
}

2.7 vector互换容器

功能描述:实现两个容器内元素进行互换

函数原型:

swap(vec);    //将vec与本身的元素互换
#include<iostream>
#include<string>
#include<vector>

using namespace std;
//打印接口
void printVector(vector<int>& v1)
{
	for (vector<int>::iterator it = v1.begin(); it != v1.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}

//普通操作
void test01()
{
	cout << "交换前" << endl;
	vector<int> v1;
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
	}
	printVector(v1);

	vector<int> v2;
	for (int j = 10; j > 0; j--)
	{
		v2.push_back(j);
	}
	printVector(v2);

	cout << "交换后" << endl;
	v1.swap(v2);
	printVector(v1);
	printVector(v2);
}

//实际操作 --- 收缩容器
void test02()
{
	vector<int> v;
	for (int i = 0; i < 10000; i++)
	{
		v.push_back(i);
	}
	v.resize(3);	//只保留前三个值
	cout << "v的容量为:" << v.capacity() << endl;		//容量很大
	cout << "v的容量为:" << v.size() << endl;			//大小为3,这样就说明开辟的空间有点多了

	//vector<int>(v)--匿名对象  
	//这里是拷贝构造利用v初始化一个匿名对象,空间大小为3
	vector<int>(v).swap(v);
	cout << "v的容量为:" << v.capacity() << endl;
	cout << "v的容量为:" << v.size() << endl;
}

int main()
{
	//test01();
	test02();
	system("pause");
	return 0;
}

2.8 vector预留空间

功能描述:减少vector在动态扩展容量时的扩展次数

函数原理:

reserve(int len)    //容量预留len个元素长度,预留位置不初始化,元素不可访问
#include<iostream>
#include<string>
#include<vector>

using namespace std;


void test01()
{
	vector<int> v1;
	//计算开辟空间次数
	int num = 0;
	int* p = NULL;

	v1.reserve(100000);			//提前预留100000空间大小,下面就会值开辟一次空间
	for (int i = 0; i < 100000; i++)
	{
		v1.push_back(i);
		if (p != &v1[0])
		{
			p = &v1[0];			//每次开辟新空间,地址就会发生改变
			num++;
		}
	}
	cout << "num= "<<num << endl;

}


int main()
{
	test01();

	system("pause");
	return 0;
}

3 deque容器

3.1 deque容器基本概念

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

deque和vector的区别:

  • vector对头部的插入删除效率低,数据量越大,效率越低
  • deque相对而言,对头部的插入删除速度比vector快
  • vector访问元素时的速度会比deque快,这和两者内部实现有关

deque的内部工作原理:

deque内部有个中控器,维护没断缓冲区中的内容,缓冲区存放真实数据,中控器维护的每个缓冲区的地址,使得使用deque时像一片连续的内存空间。deque容器的迭代器支持随机访问的

 3.2 deque构造函数

功能描述:deque容器构造

函数原型:

deque<T> deqT;                //默认构造形式
deque(beg, end);              //构造函数将[beg,end]区间的元素拷贝给自身
deque(n,elem);                //构造函数将n个elem拷贝给自身
deque(const deque &deq)       //拷贝构造函数
#include<iostream>
#include<string>
#include<deque>

using namespace std;
//当使用const修饰变量的时候,也就是只读状态,迭代器就需要换成const_iterator
void printDeque(const deque<int>& d)
{
	for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
	{
		//*it = 100;	因为是只读状态,所以这里就不能修改了
		cout << *it << " ";
	}
	cout << endl;
}

void test01()
{
	deque<int> d1;
	for (int i = 0; i < 10; i++)
	{
		d1.push_back(i);
	}
	printDeque(d1);
	
	deque<int> d2(d1.begin(), d1.end());
	printDeque(d2);

	deque<int> d3(10, 100);
	printDeque(d3);

	deque<int> d4(d3);
	printDeque(d4);
}


int main()
{
	test01();

	system("pause");
	return 0;
}

3.3 deque赋值操作

功能描述:给deque容器进行赋值

函数原型:

deque& operator=(const deque &deq);      //重载等号操作符
assign(beg, end);                        //将[beg, end]区间中的数据拷贝赋值给本身
assign(n, elem);                         //将n个elem拷贝赋值给本身
#include<iostream>
#include<string>
#include<deque>

using namespace std;
//当使用const修饰变量的时候,也就是只读状态,迭代器就需要换成const_iterator
void printDeque(const deque<int>& d)
{
	for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
	{
		//*it = 100;	因为是只读状态,所以这里就不能修改了
		cout << *it << " ";
	}
	cout << endl;
}

void test01()
{
	deque<int> d1;
	for (int i = 0; i < 10; i++)
	{
		d1.push_back(i);
	}
	printDeque(d1);
	
	//operator=  赋值
	deque<int> d2;
	d2 = d1;
	printDeque(d2);

	//assign函数赋值
	deque<int> d3;
	d3.assign(d2.begin(), d2.end());
	printDeque(d3);

	deque<int> d4;
	d4.assign(10, 100);
	printDeque(d4);
}


int main()
{
	test01();

	system("pause");
	return 0;
}

3.4 deque大小操作

功能描述:对deque容器的大小进行操作

函数原型:

deque.empty();                 //判断容器是否为空
deque.size();                  //返回容器中元素的个数
deque.resize(num);             //重新指定容器的长度为num,容容器变长,则以默认值哦填充新位置
                               //如果容器变短,则末尾超出容器长度的元素删除
deque.resize(nnu, elem)        //重新指定容器的长度为num,若容器变长,则以elem值填充新位置
                               //如果容器变短,则末尾超出容器长度的元素被删除
#include<iostream>
#include<string>
#include<deque>

using namespace std;
//当使用const修饰变量的时候,也就是只读状态,迭代器就需要换成const_iterator
void printDeque(const deque<int>& d)
{
	for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
	{
		//*it = 100;	因为是只读状态,所以这里就不能修改了
		cout << *it << " ";
	}
	cout << endl;
}

void test01()
{
	deque<int> d1;
	for (int i = 0; i < 10; i++)
	{
		d1.push_back(i);
	}
	printDeque(d1);
	
	if (d1.empty() == true)
	{
		cout << "deque容器为空" << endl;
	}
	else
	{
		cout << "deque容器不为空" << endl;
		cout << "deque容器的大小" << d1.size() << endl;
		//deque容器没有容量的概念
	}

	//重新指定大小
	d1.resize(15);
	d1.resize(15, 1);		//只有比原来大的时候才会填充1
	printDeque(d1);
}


int main()
{
	test01();

	system("pause");
	return 0;
}

3.5 deque插入和删除数据

功能描述:向deque容器中插入和删除数据

函数原型:

两端插入操作:

push_back(elem);                //在容器末尾插入elem
push_front(elem);               //在容器头部插入一个elem

pop_back();                     //删除容器的最后一个数据
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位置的数据,返回下一个数据的位置
#include<iostream>
#include<string>
#include<deque>

using namespace std;
//当使用const修饰变量的时候,也就是只读状态,迭代器就需要换成const_iterator
void printDeque(const deque<int>& d)
{
	for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
	{
		//*it = 100;	因为是只读状态,所以这里就不能修改了
		cout << *it << " ";
	}
	cout << endl;
}

//两端操作
void test01()
{
	deque<int> d1;
	//尾插
	d1.push_back(1);
	//头插
	d1.push_front(2);
	printDeque(d1);

	//尾删
	d1.pop_back();
	printDeque(d1);
	//头删
	d1.pop_front();
	printDeque(d1);
}

//指定位置操作
void test02()
{
	deque<int> d2;
	d2.push_back(1);
	d2.push_front(2);

	//insert插入
	d2.insert(d2.begin(),3);
	printDeque(d2);
	d2.insert(d2.end(), 2, 0);
	printDeque(d2);

	//指定位置删除
	d2.erase(d2.begin());
	printDeque(d2);

	//区间删除
	d2.erase(d2.begin(),d2.begin()+2);
	printDeque(d2);

	//清空
	d2.clear();
}


int main()
{
	//test01();
	test02();

	system("pause");
	return 0;
}

总结:插入和删除提供的位置都是迭代器!

3.6 deque数据存取

功能描述:对deque中的数据的存取操作

函数原型:

at(int idx);        //返回索引idx所指的数据
operator[];         //返回索引idx所指的数据
front();            //返回容器中的第一个数据元素
back();             //返回容器中最后一个数据元素
#include<iostream>
#include<string>
#include<deque>

using namespace std;

void test01()
{
	deque<int> d1;

	d1.push_back(1);
	d1.push_back(2);
	d1.push_back(3);
	d1.push_front(10);
	d1.push_front(20);
	d1.push_front(30);

	for (int i = 0; i < d1.size(); i++)
	{
		//通过[]的方式访问所有元素
		cout << d1[i] << " ";
	}
	cout << endl;

	for (int i = 0; i < d1.size(); i++)
	{
		//通过at函数的方式访问所有元素
		cout << d1.at(i) << " ";
	}
	cout << endl;

	cout << "返回最后一个数据:" << d1.back() << endl;
	cout << "返回第一个数据:" << d1.front() << endl;
}


int main()
{
	test01();


	system("pause");
	return 0;
}

总结:不但可以使用迭代器的方式遍历数据,还可以使用[]和at函数

3.7 deque排序

功能描述:利用算法实现对deque容器进行排序

算法:

sort(iterator beg,iterator end)        //对beg和end区间内的元素进行排序
#include<iostream>
#include<string>
#include<deque>
#include <algorithm> 

using namespace std;

void printDeque(deque<int> &d)
{
	for (int i = 0; i < d.size(); i++)
	{
		//通过[]的方式访问所有元素
		cout << d[i] << " ";
	}
	cout << endl;
}

void test01()
{
	deque<int> d1;

	d1.push_back(1);
	d1.push_back(2);
	d1.push_back(3);
	d1.push_front(10);
	d1.push_front(20);
	d1.push_front(30);

	printDeque(d1);

	//排序 默认规则从小到大
	sort(d1.begin(), d1.end());
	printDeque(d1);
}

int main()
{
	test01();


	system("pause");
	return 0;
}

4 案例-评委打分

4.1 案例描述

有5名选手:选手ABCD,10个评委分别对每个选手打分,去除最高分,去除评委中的最低分,取平均分

4.2 实现步骤

  1. 创建五名选手,放进vector中
  2. 遍历vector容器,取出每一个选手,执行for循环,可以把10个评分打分存在deque容器中
  3. sort算法对deque容器中分数排序,去除最高和最低分
  4. deque容器遍历一遍。累加总分
  5. 获取平均分
#include<iostream>
#include<string>
#include<deque>
#include<vector>
#include <algorithm> 

using namespace std;

class Person
{
public:
	Person(string name,int sorce)
	{
		this->m_Name = name;
		this->m_Sorce = sorce;
	}

	string m_Name;
	int m_Sorce;

};

void setSorce(vector<Person> &v)
{
	for (vector<Person>::iterator it = v.begin(); it != v.end(); it++)
	{
		deque<int> deq;
		//将随机的10个数添加到deque容器中
		for (int i = 0; i < 10; i++)
		{
			int sorce = rand() % 41 + 60;
			deq.push_back(sorce);
		}
		//将这10个数进行展示看一下
		cout << (*it).m_Name << " ";

		for (deque<int>::iterator de = deq.begin(); de != deq.end(); de++)
		{
			cout << (*de) << " ";
		}
		cout << endl;
		//排序
		sort(deq.begin(),deq.end());
		//去掉最大和最小值
		deq.pop_back();
		deq.pop_front();
		int num = 0;
		for (deque<int>::iterator de = deq.begin(); de != deq.end(); de++)
		{
			num += (*de);
		}
		(*it).m_Sorce = num / deq.size();
	}
}

void showSorce(vector<Person>& v)
{
	for (vector<Person>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << (*it).m_Name << " 平均分:" << (*it).m_Sorce << endl;
	}
}

int main()
{
	vector<Person> v;
	//1,创建5名选手,放进vector
	for (int i = 0; i < 5; i++)
	{
		string Num = "ABCDE";
		string Name = "选手";
		Name += Num[i];

		Person p(Name, 0);
		v.push_back(p);
	}
#if 0
	//测试5个选手是否放进vector容器中
	for (vector<Person>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << "姓名:" << it->m_Name << " 分数: " << it->m_Sorce << endl;
	}
#endif
	//2,设置分数
	setSorce(v);

	//3,展示平均分
	showSorce(v);

	system("pause");
	return 0;
}

5 stack容器

5.1 stack基本概念

概念:stack是一种先进后出的数据结构,他只有一个出口

 栈中只有顶端的元素才可以被外界使用,因此栈不允许有遍历行为

栈中进入数据称为----入栈push

栈中弹出数据称为----出栈pop

 5.2 stack常用接口

功能描述:栈容器常用的对外接口

构造函数:

stack<T> stk;                   //stack采样模板类实现,stack对象默认构造方式
stack(const stack &stk);        //拷贝构造函数

赋值操作:

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

数据存取:

push(elem);            //向栈顶添加元素
pop();                 //从栈顶移除第一个元素
top();                 //返回栈顶元素

大小操作:

empty();            //判断堆栈是否为空
size();             //返回栈的大小
#include<iostream>
#include<string>
#include<stack>

using namespace std;

//stack(栈)的接口
void test01()
{
	stack<int> s;
	
	//入栈
	s.push(10);
	s.push(20);
	s.push(30);

	//查看栈中的元素   先进后出  且只能查看栈顶元素
	while (!s.empty())
	{
		//查看栈顶
		cout << "栈顶元素为:" << s.top() << endl;

		//出栈
		s.pop();
	}
	cout << "剩下多少个元素" << s.size() << endl;

}

int main()
{
	test01();

	system("pause");
	return 0;
}

6 queue容器

6.1 queue基本概念

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

队列容器允许从一段新增数据,从另一端移除数据

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

队列中的进数据称为----入队push

队列中的出数据称为----出队pop

#include<iostream>
#include<string>
#include<queue>

using namespace std;

//queue(队列)的接口
void test01()
{
	queue<int> q;
	
	//入栈
	q.push(10);
	q.push(20);
	q.push(30);

	//查看队列中的元素   先进后出  可以查看队头和队尾
	while (!q.empty())
	{
		//查看
		cout << "队头元素为:" << q.front() << endl;

		//查看
		cout << "队尾元素为:" << q.back() << endl;

		//出栈
		q.pop();
	}
	cout << "剩下多少个元素" << q.size() << endl;

}

int main()
{
	test01();

	system("pause");
	return 0;
}

7 list容器

7.1 list基本概念

功能:将数据进行链式存储

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

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

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

STL中的链表是一个双向循环链表

由于链表的存储方式并不是连续的内存空间,因此链表list的迭代器只支持前移和后移,属于双向迭代器

list的优点:

  • 采用动态存储分配,不会造成内存的浪费和溢出
  • 链表执行插入和删除操作十分方便,修改指针即可,不需要移动大量元素

list的缺点:

  • 链表灵活,但是空间(指针域)和时间(遍历)额外耗费较大

list有一个重要的性质,插入和删除操作都不会造成原有的list迭代器失效,这在vector是不成立的

总结:STL中list和vector是两个最常用到的容器,各有优缺点

7.2 list构造函数

功能描述:创建list容器

函数原型:

list<T> lst;                //list采用模板类实现,对象的默认构造形式
list(beg,end);              //构造函数将【beg,end】区间中的元素拷贝给本身
list(n,elem);               //构造函数将n个elem拷贝给本身
list(const list &lst)       //拷贝构造函数
#include<iostream>
#include<string>
#include<list>

using namespace std;
void printList(list<int> &v)
{
	for (list<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << (*it) << " ";
	}
	cout << endl;
}

void test01()
{
	//默认构造
	list<int> L1;
	//插入数据
	L1.push_back(10);
	L1.push_back(20);
	L1.push_back(30);
	printList(L1);

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

	list<int> L3(L2);		//拷贝构造
	printList(L2);

	list<int> L4(2,100);	//n个elem
	printList(L2);
}

int main()
{
	test01();

	system("pause");
	return 0;
}

7.3 list赋值和交换

功能描述:给list容器进行赋值,以及交换容器

函数原型:

assign(beg,end)                          //将【beg,end】区间的数据拷贝赋值给本身
assign(n,elem)                           //将n个elem拷贝赋值给本身
list& operator=(const list &lst)         //重载等号运算符
swap(lst)                                //将lst与本身的元素互换
#include<iostream>
#include<string>
#include<list>

using namespace std;
void printList(list<int> &v)
{
	for (list<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << (*it) << " ";
	}
	cout << endl;
}
//赋值
void test01()
{
	//默认构造
	list<int> L1;
	//插入数据
	L1.push_back(10);
	L1.push_back(20);
	L1.push_back(30);
	printList(L1);

	//operator= 赋值
	list<int> L2;
	L2 = L1;
	printList(L2);

	//assign赋值操作
	list<int> L3;
	L3.assign(L2.begin(), L2.end());
	printList(L3);

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

//交换
void test02()
{
	list<int> L1;
	//插入数据
	L1.push_back(10);
	L1.push_back(20);
	L1.push_back(30);

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

	cout << "交换前" << endl;
	printList(L1);
	printList(L2);
	L1.swap(L2);
	cout << "交换后" << endl;
	printList(L1);
	printList(L2);
}


int main()
{
	test01();
	test02();
	system("pause");
	return 0;
}

7.4 list大小操作

功能描述:对list容器的大小进行操作

函数原型:

size();                 //返回容器中元素的个数
empty();                //判断容器是否为空
resize(num);            //重新指定容器的长度为num,容容器变长,则以默认值填充新位置
                        //如果容器变短,则末尾超出容器长度的元素被删除
resize(num,elem)        //重新指定容器的长度为num,容容器变长,则以elem填充新位置
                        //如果容器变短,则末尾超出容器长度的元素被删除
#include<iostream>
#include<string>
#include<list>

using namespace std;
void printList(list<int> &v)
{
	for (list<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << (*it) << " ";
	}
	cout << endl;
}
//赋值
void test01()
{
	//默认构造
	list<int> L1;
	//插入数据
	L1.push_back(10);
	L1.push_back(20);
	L1.push_back(30);
	printList(L1);

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

	L1.resize(5);
	printList(L1);
}


int main()
{
	test01();

	system("pause");
	return 0;
}

7.5 list插入和删除

功能描述:对list容器进行数据的插入和删除

函数原型:

push_back(elem);                //在容器尾部加入一个元素
pop_back();                     //删除容器尾部最后一个元素
push_front(elem);               //在容器头部加入一个元素
pop_front();                    //删除容器头部第一个元素
insert(pos,elem);               //在pos位置插入一个elem,返回新数据的位置
insert(pos,n,elem);             //在pos位置插入n个elem数据,无返回值
insert(pso,beg,end);            //在pos位置插入【beg,end】区间的数据,无返回值
clear();                        //移除容器中的所有数据
erase(beg,end);                 //删除【beg,end】区间的数据,返回下一个数据的位置
erase(pos);                     //删除pos位置的数据,返回下一个数据的位置
remove(elem);                   //删除容器中所有与elem值匹配的元素
#include<iostream>
#include<string>
#include<list>

using namespace std;
void printList(list<int> &v)
{
	for (list<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << (*it) << " ";
	}
	cout << endl;
}
//赋值
void test01()
{
	list<int> L1;
	//尾插
	L1.push_back(10);
	L1.push_back(20);
	L1.push_back(30);
	//头插
	L1.push_front(100);
	L1.push_front(200);
	L1.push_front(300);
	printList(L1);

	//尾删和头删
	L1.pop_back();
	L1.pop_front();
	printList(L1);

	//insert插入
	list<int>::iterator it = L1.begin();
	//L1.insert(it + 2, 0);		//这里直接加一个int的类型的数据就是直接报错,是因为链表的地址不是连续的,这样是找不到指定位置的
								//但是可以L1.insert(++it, 0),可以说明链表的迭代器只能前置加1
	L1.insert(++it, 1000);
	printList(L1);

	//erase删除
	L1.erase(++it);
	printList(L1);
	//remove删除
	L1.remove(1000);
	printList(L1);
	//clear清除
	L1.clear();
	printList(L1);
}


int main()
{
	test01();

	system("pause");
	return 0;
}

7.6 数据存取

功能描述:对list容器中的数据存取

函数原型:

front();        //返回第一个元素
back();         //返回最后一个元素
#include<iostream>
#include<string>
#include<list>

using namespace std;
void printList(list<int> &v)
{
	for (list<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << (*it) << " ";
	}
	cout << endl;
}
//赋值
void test01()
{
	list<int> L1;
	//尾插
	L1.push_back(10);
	L1.push_back(20);
	L1.push_back(30);
	
	cout << "第一个元素" << L1.front() << endl;
	cout << "最后一个元素" << L1.back() << endl;

	//cout << L1[0]			错误,不支持[]方式访问
	//cout << L1.at(0)			错误,不支持at方式访问
	//list容器的迭代器是双向迭代器,不支持随机访问   例如L1.begin()+3
}


int main()
{
	test01();

	system("pause");
	return 0;
}

总结:

  • list容器不可以通过[]或者at方式访问数据
  • 返回第一个元素---front
  • 返回最后一个元素---back

7.7 list反转和排序

功能描述:将容器中的元素反转,以及将容器中的数据进行排序

函数原型:

reverse();             //反转链表
sort();                //链表排序
#include<iostream>
#include<string>
#include<list>

using namespace std;
void printList(list<int> &v)
{
	for (list<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << (*it) << " ";
	}
	cout << endl;
}

//仿函数
bool mySort(int v1, int v2)
{
	return v1 > v2;
}


void test01()
{
	list<int> L1;
	//尾插
	L1.push_back(50);
	L1.push_back(20);
	L1.push_back(30);
	L1.push_back(40);
	L1.push_back(10);
	
	cout << "反转前" << endl;
	printList(L1);

	cout << "反转后" << endl;
	L1.reverse();
	printList(L1);

	cout << "默认排序" << endl;
	//所有不支持随机访问迭代器的容器,不可以使用标志算法   例如:sort(L1.begin(),L1.end())
	//不支持随机访问的迭代器的容器,内部会提供对应一些算法
	L1.sort();
	printList(L1);

	cout << "从大到小排序" << endl;
	L1.sort(mySort);
	printList(L1);
}


int main()
{
	test01();

	system("pause");
	return 0;
}

8 set/multiset 容器

8.1 set基本概念

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

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

set和multiset区别:set不允许容器中有重复的元素,mutliset允许容器中有重复的元素

8.2 set构造和赋值

功能描述:创建set容器以及赋值

构造:

set<T> st;            //默认构造函数
set(const set &s);    //拷贝构造函数

赋值:

set& operator=(const set &s);      //重载等号操作符
#include<iostream>
#include<string>
#include<set>

using namespace std;
void printSet(set<int> &s)
{
	for (set<int>::iterator it = s.begin(); it != s.end(); it++)
	{
		cout << (*it) << " ";
	}
	cout << endl;
}


void test01()
{
	//set容器
	set<int> s;

	//insert插入数据   set容器只允许insert插入,且插入的数据会自动排序
	s.insert(20);
	s.insert(10);
	s.insert(30);
	s.insert(20);		//set不允许插入相同的数,其实就是插入相同的数相当于白插,没有用
	
	printSet(s);

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

	//operator=  赋值
	set<int> s2;
	s2 = s1;
	printSet(s2);
}


int main()
{
	test01();

	system("pause");
	return 0;
}

总结:set容器插入只能用inset,且插入的数据会自动排序

8.3 set大小和交换

功能描述:统计set容器大小以及交换set容器

函数原型:

size();              //返回容器中元素的个数
empty();             //判断容器是否为空
swap(st);            //减缓两个集合容器
#include<iostream>
#include<string>
#include<set>

using namespace std;
void printSet(set<int> &s)
{
	for (set<int>::iterator it = s.begin(); it != s.end(); it++)
	{
		cout << (*it) << " ";
	}
	cout << endl;
}


void test01()
{
	//set容器
	set<int> s;

	//insert插入数据   set容器只允许insert插入,且插入的数据会自动排序
	s.insert(20);
	s.insert(10);
	s.insert(30);
	s.insert(20);		//set不允许插入相同的数,其实就是插入相同的数相当于白插,没有用
	
	printSet(s);

	if (s.empty())
	{
		cout << "容器为空" << endl;
	}
	else 
	{
		cout << "容器不为空" << endl;
		cout << "容器中元素为" << s.size() << endl;
	}

	//交换
	set<int> s2;
	s2.insert(20);
	s2.insert(10);

	s2.swap(s);
	printSet(s);
	printSet(s2);
}


int main()
{
	test01();

	system("pause");
	return 0;
}

8.4 set插入和删除

功能描述:set容器进行插入数据和删除数据

函数原型:

insert(elem);           //在容器中插入元素
clear();                //清除容器中的所有元素
erase(pos);             //清除指定位置的元素
erase(beg,end);         //清除【beg,end】区间的元素
erase(elem);            //清除容器中所有elem元素
#include<iostream>
#include<string>
#include<set>

using namespace std;
void printSet(set<int> &s)
{
	for (set<int>::iterator it = s.begin(); it != s.end(); it++)
	{
		cout << (*it) << " ";
	}
	cout << endl;
}


void test01()
{
	//set容器
	set<int> s;

	//insert插入数据   set容器只允许insert插入,且插入的数据会自动排序
	s.insert(20);
	s.insert(10);
	s.insert(30);
	s.insert(40);		
	printSet(s);

	//删除
	s.erase(s.begin());
	printSet(s);

	s.erase(30);
	printSet(s);
	//清空
	s.erase(s.begin(), s.end());
	s.clear();
	printSet(s);
}


int main()
{
	test01();

	system("pause");
	return 0;
}

 8.5 set查找和统计

功能描述:对set容器进行查找数据以及统计数据

函数原型:

find(elem);           //查找elem是否存在,若存在,返回元素迭代器,不存在,返回set.end()
count(elem);          //统计elem的元素个数
#include<iostream>
#include<string>
#include<set>

using namespace std;
void printSet(set<int> &s)
{
	for (set<int>::iterator it = s.begin(); it != s.end(); it++)
	{
		cout << (*it) << " ";
	}
	cout << endl;
}


void test01()
{
	//set容器
	set<int> s;

	//insert插入数据   set容器只允许insert插入,且插入的数据会自动排序
	s.insert(20);
	s.insert(10);
	s.insert(30);
	s.insert(40);		
	printSet(s);

	//查找,返回的是一个迭代器,所以也需要用一个迭代器来接收
	set<int>::iterator pos = s.find(30);

	//判断是否找到的方法
	if (pos == s.end())
	{
		cout << "未找到元素" << endl;
	}
	else
	{
		cout << "找到元素:" << (*pos) << endl;
	}

	//统计确定元素的个数,对于set容器而言,要么是1要么是0,因为容器中不允许插入相同值
	cout << "30的个数:" << s.count(30) << endl;
}


int main()
{
	test01();

	system("pause");
	return 0;
}

总结:

  • 查找 --- find   (返回的是迭代器)
  • 统计 --- count  (对于set,结果为1或者0)

8.6 set和multiset区别

学习目标:掌握set和multise的区别

区别:

  • set不可以插入重复值,而multiset可以
  • set插入数据的同时会返回插入结果,表示插入是否成功
  • multiset不会检测数据,因此可以插入重复数据
#include<iostream>
#include<string>
#include<set>

using namespace std;

void test01()
{
	//set容器
	set<int> s;

	//set容器插入数据会返回pair类型,这个类型会告诉你插入的位置(迭代器),还有插入是否成功(bool)
	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);
	ms.insert(10);
	for (multiset<int>::iterator it = ms.begin(); it != ms.end(); it++)
	{
		cout << (*it) << " ";
	}
	cout << endl;
}


int main()
{
	test01();

	system("pause");
	return 0;
}

总结:

  • 如果不允许插入重复数据可以利用set
  • 如果允许插入重复数据可以利用multiset

8.7 pair对组创建

功能描述:成对出现的数据,利用对组可以返回两个数据

两种创建方式:

pair<type,type> p(value1,value2);
pair<type,type> p = make_pair(value1,value2);
#include<iostream>
#include<string>

using namespace std;

void test01()
{
	//对组,想要创建两个数据的时候可以使用对组
	//第一种创建方式
	pair<string, int> p("jackie", 20);
	cout << "姓名:" << p.first << " 年龄:" << p.second << endl;

	//第一种创建方式
	pair<string, int> p1 = make_pair("jackie", 20);
	cout << "姓名:" << p1.first << " 年龄:" << p1.second << endl;
}


int main()
{
	test01();

	system("pause");
	return 0;
}

总结:两种方式都可以创建对组,选择一直即可

8.8 set容器排序

学习目标:set容器默认排序规则从小到大,掌握如何改变排序规则

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

set存放内置的数据类型

#include<iostream>
#include<string>
#include<set>

using namespace std;

class MyCompare
{
public:
	//重载()运算符  仿函数
	bool operator()(int value1, int value2)const
	{
		return value1 > value2;
	}
};


void test01()
{
	//指定排序规则 从大到小
	set<int,MyCompare> s;
	
	s.insert(40);
	s.insert(20);
	s.insert(30);
	s.insert(10);
	for (set<int, MyCompare>::iterator it = s.begin(); it != s.end(); it++)
	{
		cout << (*it) << " ";
	}
	cout << endl;
}


int main()
{
	test01();

	system("pause");
	return 0;
}

总结:利用仿函数可以指定set容器的排序规则

set存放自定义的数据类型

#include<iostream>
#include<string>
#include<set>

using namespace std;

class Person
{
public:
	Person(string name, int age)
	{
		this->Name = name;
		this->Age = age;
	}
	string Name;
	int Age;
};


class MyCompare
{
public:
	//重载()运算符  仿函数
	bool operator()(Person p1, Person p2)const
	{
		return p1.Age > p2.Age;
	}
};


void test01()
{
	//自定义的数据类型,必须指定排序规则,因为默认的排序规则不知道自定义的数据类型如何排序
	set<Person,MyCompare> s;
	
	Person p1("张飞", 24);
	Person p2("关羽", 22);
	Person p3("刘备", 27);
	Person p4("赵云", 25);

	s.insert(p1);
	s.insert(p2);
	s.insert(p3);
	s.insert(p4);

	for (set<Person, MyCompare>::iterator it = s.begin(); it != s.end(); it++)
	{
		cout << it->Name << " " << it->Age << endl;
	}
}


int main()
{
	test01();

	system("pause");
	return 0;
}

总结:对于自定义的数据类型,set容器必须指定排序规则才能插入数据

9 map/multimap容器

9.1 map基本概念

简介:

  • map中所有的元素都是pair
  • pair中的第一个元素为key(键值),起到索引作用,第二个元素为value(实值)
  • 所有元素都会根据元素的键值自动排序

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

优点:可以根据key值快速找到value值

map/multimap的区别:map不允许容器中有重复的key值元素,multimap允许中有重复的key值

9.2 map构造和赋值

功能描述:对map容器进行构造和赋值操作

函数原理:

构造:

map<T1,T2> mp;             //map默认构造函数
map<const map &mp>;        //拷贝构造函数

赋值:

map& operator=(const map &mp);        //重载等号操作符
#include<iostream>
#include<string>
#include<map>

using namespace std;

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


void test01()
{
	//默认构造
	map<int, int> m1;

	//插入数据 必须是pair类型  下面是匿名对象
	m1.insert(pair<int,int>(1,10));
	pair<int, int> p1(3, 30);		//非匿名对象
	m1.insert(p1);
	m1.insert(pair<int, int>(2, 20));
	m1.insert(pair<int, int>(4, 40));

	//遍历容器
	printMap(m1);
}

int main()
{
	test01();

	system("pause");
	return 0;
}

9.3 map大小和交换

功能描述:统计map容器大小以及交换map容器

函数原型:

size();          //返回容器中元素的数目
empty();         //判断容器是否为空
swap(st);        //交换两个容器集合
#include<iostream>
#include<string>
#include<map>

using namespace std;

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


void test01()
{
	//默认构造
	map<int, int> m1;

	//插入数据 必须是pair类型  下面是匿名对象
	m1.insert(pair<int, int>(1, 10));
	m1.insert(pair<int, int>(2, 20));
	m1.insert(pair<int, int>(3, 30));
	m1.insert(pair<int, int>(4, 40));

	if (m1.empty())
	{
		cout << "容器为空" << endl;
	}
	else
	{
		cout << "容器不为空" << endl;
		cout << "容器的大小为:" << m1.size() << endl;
	}

	cout << "交换后" << endl;
	map<int, int> m2;
	m2.insert(pair<int, int>(5, 500));
	m2.insert(pair<int, int>(6, 600));
	m2.swap(m1);	//交换
	printMap(m1);
	printMap(m2);
}

int main()
{
	test01();

	system("pause");
	return 0;
}

9.4 map插入和删除

功能描述:map容器进行插入数据和删除数据

函数原型:

insert(elem);              //在容器中插入元素
clear();                   //清除所有元素
erase(pos);                //删除pos迭代器所指的元素,返回下一个元素的迭代器
erase(beg,end);            //删除区间的所有元素,返回下一个元素的迭代器
erase(key);                //删除容器中值为key的元素
#include<iostream>
#include<string>
#include<map>

using namespace std;

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


void test01()
{
	//插入
	map<int, int> m1;

	//第一种插入方式
	m1.insert(pair<int, int>(1, 10));

	//第二种插入方式
	m1.insert(make_pair(2, 20));

	//第三种插入方式
	m1.insert(map<int, int>::value_type(3, 30));
	
	//第四种插入方式	不建议使用第四种方式,其主要作用是用key找到value值  cout << m1[4] << endl;
	m1[4] = 40;

	printMap(m1);

	//erase删除
	m1.erase(m1.begin());
	printMap(m1);

	m1.erase(3);
	printMap(m1);

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

int main()
{
	test01();

	system("pause");
	return 0;
}

总结:使用[]的方式插入,如果里面原先有对应的key值,会被覆盖,其他方式则不会,所以不推荐第四种插入方式。

9.5 map查找和统计

功能描述:对map容器进行查找数据以及统计数据

函数原型:

fine(key);          //查找key是否存在,若存在,返回该键的元素的迭代器,若不存在,返回map.end();
count(key);         //统计key的元素的个数
#include<iostream>
#include<string>
#include<map>

using namespace std;

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


void test01()
{
	//插入
	map<int, int> m1;

	m1.insert(pair<int, int>(1, 10));
	m1.insert(pair<int, int>(2, 20));
	m1.insert(pair<int, int>(3, 30));
	//查找,返回的是位置的迭代器,不存在,返回的m1.end()
	map<int, int>::iterator pos = m1.find(3);
	if (pos != m1.end())
	{
		cout << "key = " << (*pos).first << " value = " << (*pos).second << endl;
	}
	else
	{
		cout << "元素不存在" << endl;
	}

	//map统计对应元素的个数除了0就是1,multimap可以大于1
	int num = m1.count(3);
	cout << "num = " << num << endl;
}

int main()
{
	test01();

	system("pause");
	return 0;
}

总结:查找 --- find   返回的是迭代器

           统计 --- count  对于map而言,结果为1或者0

9.6 map容器排序

学习目标:map容器默认排序规则为按照key值进行从小到大的排序,掌握如何改变排序规则

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

#include<iostream>
#include<string>
#include<map>

using namespace std;


//仿函数
class MyCompair
{
public:
	bool operator()(int v1, int v2)const
	{
		//降序
		return v1 > v2;
	}
};

void test01()
{
	//默认排序从小到大,修改排序规则
	//利用仿函数修改
	map<int, int,MyCompair> m1;

	m1.insert(make_pair(1, 10));
	m1.insert(make_pair(2, 20));
	m1.insert(make_pair(3, 30));

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

int main()
{
	test01();

	system("pause");
	return 0;
}

总结:

  • 利用仿函数可以指定map容器的排序规则
  • 对于自定义的数据类型,map必须指定排序规则,同set容器

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值