C++从入门到精通 第十四章(STL容器)【上】

news2024/11/16 6:38:33

 写在前面:

  1. 本系列专栏主要介绍C++的相关知识,思路以下面的参考链接教程为主,大部分笔记也出自该教程,笔者的原创部分主要在示例代码的注释部分。
  2. 除了参考下面的链接教程以外,笔者还参考了其它的一些C++教材(比如计算机二级教材和C语言教材),笔者认为重要的部分大多都会用粗体标注(未被标注出的部分可能全是重点,可根据相关部分的示例代码量和注释量判断,或者根据实际经验判断)。
  3. 如有错漏欢迎指出。

参考教程:黑马程序员匠心之作|C++教程从0到1入门编程,学习编程不再难_哔哩哔哩_bilibili

一、string容器

1、string容器概述

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

(2)string和char *的区别:char *是一个指针,而string是一个类,类内部封装了char*,管理这个字符串,是一个char*型的容器。

(3)string 类内部封装了很多成员方法,例如查找find、拷贝copy、删除delete、替换replace、插入insert。

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

2、string类的构造函数

string();                //创建一个空的字符串(默认构造)

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

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

#include<iostream>
#include<string>
using namespace std;

void test01()  
{
	string s1;      //默认构造

	const char * str = "Hello world";    //使用字符串初始化
	string s2(str);                      //这个也可视作拷贝构造
	cout << "s2 : " << s2 << endl;

	string s3(s2);   //拷贝构造
	cout << "s2 : " << s2 << endl;

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

int main() {

	test01();

	system("pause");

	return 0;
}

3、string类的赋值操作

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

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

string& operator=(char 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>
using namespace std;
#include<vector>

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

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

	string str3;
	str3 = 'a';
	cout << "srt3 = " << str3 << endl;

	string str4;
	str4.assign("Hello C++");
	cout << "srt4 = " << str4 << endl;

	string str5;
	str5.assign("Hello C++", 5);
	cout << "srt5 = " << str5 << endl;

	string str6;
	str6.assign(str5);
	cout << "srt6 = " << str6 << endl;

	string str7;
	str7.assign(10, 'w');
	cout << "srt7 = " << str7 << endl;
}

int main() {

	test01();

	system("pause");

	return 0;
}

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;

void test01()   
{
	string str1;
	str1 = "我";
	str1 += "爱玩游戏";
	cout << "str1 = " << str1 << endl;
	str1 += ':';
	cout << "str1 = " << str1 << endl;
	string str2 = " LOL DNF";
	str1 += str2;
	cout << "str1 = " << str1 << endl;

	string str3 = "I";
	str3.append(" love ");
	cout << "str3 = " << str3 << endl;
	str3.append("Python abcde", 6);
	cout << "str3 = " << str3 << endl;
	str3.append(str2);
	cout << "str3 = " << str3 << endl;
	str3.append(str2, 0, 4);     //参数2:从哪个位置开始截取
	cout << "str3 = " << str3 << endl;
	str3.append(str2, 4, 4);     //参数3:截取字符个数
	cout << "str3 = " << str3 << endl;
}

int main() {

	test01();

	system("pause");

	return 0;
}

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, 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 str1 = "abcdefgcd";        //该字符串有两个“cd”
	int pos = str1.find("cd");      //find从左往右查
	if (pos == -1)
	{
		cout << "未找到字符串" << endl;
	}
	else
	{
		cout << "pos = " << pos << endl;
	}
	pos = str1.find("df");
	if (pos == -1)
	{
		cout << "未找到字符串" << endl;
	}
	else
	{
		cout << "pos = " << pos << endl;
	}
	
	pos = str1.rfind("cd");       //rfind从右往左查(位置编号还是从左往右算)
	cout << "pos = " << pos << endl;
	
}

void test02()     //替换
{
	string str1 = "abcdefg";
	str1.replace(2, 3, "kkkk");    //从2号位置起的3个字符替换为“kkkk”
	cout << "str1 = " << str1 << endl;
}

int main() {

	test01();
	test02();

	system("pause");

	return 0;
}

6、string字符串比较函数

比较方式:字符串比较是从第一个字符开始,按字符的ASCII码进行对比,只要出现同位置字符ASCII码不同的情况,那么两个字符串就不相等,认为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;

string compare(string &str1,string &str2)
{
	if (str1.compare(str2) == 0)
	{
		return " 等于= ";
	}
	else if (str1.compare(str2) == 1)
	{
		return " 大于> ";
	}
	else if(str1.compare(str2) == -1)
	{
		return " 小于< ";
	}
}

void test01()     
{
	string str1 = "hello";
	string str2 = "hello";
	string str3 = "xello";
	string str4 = "heklo";
	cout << "str1" << compare(str1, str2) << "str2" << endl;
	cout << "str1" << compare(str1, str3) << "str3" << endl;
	cout << "str1" << compare(str1, str4) << "str4" << endl;
}

int main() {

	test01();

	system("pause");

	return 0;
}

7、string字符串的字符存取

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

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

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

#include<iostream>
#include<string>
using namespace std;

void test01()     
{
	string str = "Hello world";
	//通过[]访问单个字符
	for (int i = 0; i < str.size(); i++)
	{
		cout << str[i] << " ";
	}
	cout << endl;
	str[0] = 'h';
	//通过at方式访问单个字符
	for (int i = 0; i < str.size(); i++)
	{
		cout << str.at(i) << " ";
	}
	cout << endl;
	str.at(0) = 'H';
	for (int i = 0; i < str.size(); i++)
	{
		cout << str.at(i) << " ";
	}
	cout << endl;
}

int main() {

	test01();

	system("pause");

	return 0;
}

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

对string字符串进行插入和删除操作时,要将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

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

#include<iostream>
#include<string>
using namespace std;

void test01()     
{
	string str = "Hello";
	str.insert(1, "k2k");   //插入
	cout << "str = " << str << endl;
	str.erase(1, 3);        //删除
	cout << "str = " << str << endl;
}

int main() {

	test01();

	system("pause");

	return 0;
}

9、从字符串string获取子串

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

#include<iostream>
#include<string>
using namespace std;

void test01()     
{
	string str = "abcdefg";
	string subStr = str.substr(1, 3);
	cout << "subStr = " << subStr << endl;
}
void test02()
{
	string email = "zhangsan@sina.com";
	int pos = email.find("@");
	string usrName = email.substr(0, pos);
	cout << "usrName = " << usrName << endl;
}

int main() {

	test01();
	test02();

	system("pause");

	return 0;
}

二、vector容器

1、vector的基本概念

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

(2)vector与普通数组区别:数组是静态空间,而vector可以动态扩展,而动态扩展并不是在原空间之后续接新空间,而是找更大的内存空间,然后将原数据拷贝新空间,释放原空间。

(3)vector容器的迭代器是支持随机访问的迭代器。

2、vector的构造函数

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

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

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

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

#include<iostream>
#include<vector>
using namespace std;

void printVector(vector<int> &v)
{
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << *it << "  ";
	}
	cout << endl;
}

void test01()     
{
	vector<int> v1;                          //默认构造(无参构造)
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
	}
	printVector(v1);
	vector<int> v2(v1.begin(), v1.end());    //通过区间方式进行构造
	printVector(v2);
	vector<int> v3(10, 199);                 //n个elem方式构造
	printVector(v3);
	vector<int> v4(v3);                      //拷贝构造
	printVector(v4);
}

int main() {

	test01();

	system("pause");

	return 0;
}

3、vector的赋值操作

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

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

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

#include<iostream>
#include<vector>
using namespace std;

void printVector(vector<int> &v)
{
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << *it << "  ";
	}
	cout << endl;
}

void test01()     
{
	vector<int> v1;
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
	}
	printVector(v1);
	vector<int>v2;
	v2 = v1;          //赋值 operator=
	printVector(v2);
	vector<int>v3;
	v3.assign(v1.begin(), v1.end());   //赋值 assign
	printVector(v3);
	vector<int>v4;
	v4.assign(10, 51);                 //赋值 n个elem方式
	printVector(v4);
}

int main() {

	test01();

	system("pause");

	return 0;
}

4、vector的容量和大小

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

capacity();     //容器的容量

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

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

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

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

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

#include<iostream>
#include<vector>
using namespace std;

void printVector(vector<int> &v)
{
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << *it << "  ";
	}
	cout << endl;
}

void test01()     
{
	vector<int> v1,v2;
	if (v1.empty())
	{
		cout << "容器v1为空" << endl;
	}
	cout << endl;
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
	}
	printVector(v1);
	if (v1.empty())
	{
		cout << "容器v1为空" << endl;
	}
	else
	{
		cout << "容器v1不为空" << endl;
		cout << "v1的容量为" << v1.capacity() << endl;
		cout << "v1的元素个数为" << v1.size() << endl;
	}
	v1.resize(15);
	printVector(v1);    //如果重新指定的长度比原来长了,默认用0填充新位置
	cout << "v1的容量为" << v1.capacity() << endl;
	cout << "v1的元素个数为" << v1.size() << endl;
	v2 = v1;
	v2.resize(8);
	printVector(v2);    //如果重新指定的长度比原来短,则超出长度的元素会被删除
	v2.resize(12, 10);
	printVector(v2);    //重新指定容器的长度,若容器变长,则以elem值填充新位置
}

int main() {

	test01();

	system("pause");

	return 0;
}

5、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<vector>
using namespace std;

void printVector(vector<int> &v)
{
	int j = 0;
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << *it << "  ";
		j++;
	}
	if (j == 0)
	{
		cout << "什么也没有" << endl;
	}
	cout << endl;
}

void test01()     
{
	vector<int> v1;
	v1.push_back(10);  //尾插
	v1.push_back(20);
	v1.push_back(30);
	v1.push_back(40);
	v1.push_back(50);
	printVector(v1);
	v1.pop_back();    //尾删
	printVector(v1);
	v1.insert(v1.begin(), 100);   //插入  第一个参数是迭代器
	printVector(v1);
	v1.insert(v1.begin(), 2 ,100);
	printVector(v1);
	v1.erase(v1.begin());         //删除 参数是迭代器
	printVector(v1);
	v1.erase(v1.begin(), v1.end());   //v1.clear();具有同等作用
	printVector(v1);
}

int main() {

	test01();

	system("pause");

	return 0;
}

6、vector的数据存取

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

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

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

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

#include<iostream>
#include<vector>
using namespace std;

void test01()     
{
	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;
	//利用at方式访问元素
	for (int i = 0; i < v1.size(); i++)
	{
		cout << v1.at(i) << " ";
	}
	cout << endl;
	cout << "第一个元素为: " << v1.front() << endl;
	cout << "最后一个元素为: " << v1.back() << endl;
}

int main() {

	test01();

	system("pause");

	return 0;
}

7、vector的互换容器操作

swap(vec);   //将vec中的元素与调用该函数的对象本身的元素互换

#include<iostream>
#include<vector>
using namespace std;

void printVector(vector<int> &v)
{
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << *it << "  ";
	}
	cout << endl;
}

void test01()     
{
	cout << "交换前:" << endl;
	vector<int> v1;
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i * 10);
	}
	printVector(v1);
	vector<int> v2;
	for (int i = 9; i > -1; i--)
	{
		v2.push_back(i * 10);
	}
	printVector(v2);
	cout << "交换后:" << endl;
	v1.swap(v2);
	printVector(v1);
	printVector(v2);
}

void test02()      //巧用swap可以收缩内存空间
{
	vector<int>v;
	for (int i = 0; i < 100000; i++)
	{
		v.push_back(i);
	}
	cout << "v的容量为:" << v.capacity() << endl;
	cout << "v的大小为:" << v.size() << endl;
	v.resize(3);   //重新指定大小
	cout << "v的容量为:" << v.capacity() << endl;   //容量不会变小
	cout << "v的大小为:" << v.size() << endl;
	vector<int>(v).swap(v);            //vector<int>(v)--匿名对象,按照v的元素给它初始化,本行过后匿名对象被销毁
	cout << "v的容量为:" << v.capacity() << endl;   //容量变小
	cout << "v的大小为:" << v.size() << endl;
}

int main() {

	test01();
	test02();

	system("pause");

	return 0;
}

8、vector允许预留空间

预留空间也就是先在内存划分一片属于vector对象的空间,这部分空间可以不立即使用,这样可以减少vector在动态扩展容量时的扩展次数。

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

#include<iostream>
#include<vector>
using namespace std;

void test01()     
{
	vector<int> v;
	v.reserve(100000);   //预留空间
	int num = 0;    //统计开辟内存次数
	int *p = NULL;
	for (int i = 0; i < 100000; i++)
	{
		v.push_back(i);
		if (p != &v[0])
		{
			p = &v[0];
			num++;
		}
	}
	cout << "num = " << num << endl;
}

int main() {

	test01();

	system("pause");

	return 0;
}

三、deque容器

1、deque容器的基本概念

(1)deque容器是一个双端数组,可以对头端进行插入删除操作。

(2)deque与vector的区别:

①vector在头部插入或删除元素的效率低,数据量越大,效率越低。

②deque在头部插入元素或删除元素的速度比vector快。

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

(3)deque内部的工作原理:

①deque内部有个中控器维护每段缓冲区中的内容,缓冲区中存放真实数据。

②中控器维护的是每个缓冲区的地址,使得使用deque时像是使用一片连续的内存空间。

(4)deque容器的迭代器也是支持随机访问的。

2、deque的构造函数

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

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

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

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

#include<iostream>
#include<deque>
using namespace std;

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、deque的赋值操作

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

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

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

#include<iostream>
#include<deque>
using namespace std;

void printDeque(const deque<int> &d)
{
	for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
	{
		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(d1.begin(), d1.end());
	printDeque(d3);

	//n个elem方式赋值
	deque<int>d4(10, 100);
	printDeque(d4);
}

int main() {

	test01();

	system("pause");

	return 0;
}

4、deque的大小

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

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

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

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

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

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

#include<iostream>
#include<deque>
using namespace std;

void printDeque(const deque<int> &d)
{
	for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
	{
		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())
	{
		cout << "容器d1为空" << endl;
	}
	cout << "d1中的元素个数为:" << d1.size() << endl;   //deque没有“容量”的概念
	d1.resize(15);
	printDeque(d1);
	d1.resize(8);
	printDeque(d1);
	d1.resize(15, 1);
	printDeque(d1);
}

int main() {

	test01();

	system("pause");

	return 0;
}

5、deque的插入和删除

//两端的插入操作:

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

push_front(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<deque>
using namespace std;

void printDeque(const deque<int> &d)
{
	for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
	{
		cout << *it << "  ";
	}
	cout << endl;
}

void test01()     
{
	deque<int>d1;
	for (int i = 0; i < 10; i++)
	{
		d1.push_back(i);      //尾插
		d1.push_front(i * 2); //头插
	}
	printDeque(d1);
	d1.pop_back();
	printDeque(d1);
	d1.pop_front();
	printDeque(d1);
}
void test02()
{
	deque<int>d1;
	for (int i = 0; i < 10; i++)
	{
		d1.push_back(i);
	}
	d1.insert(d1.begin(), 30);
	printDeque(d1);
	d1.insert(d1.begin(), 2, 40);
	printDeque(d1);
	deque<int>d2;
	for (int i = 0; i < 10; i++)
	{
		d2.push_front(i);
	}
	d1.insert(d1.begin()+1, d2.begin(), d2.end());
	printDeque(d1);
}
void test03()
{
	deque<int>d1;
	for (int i = 0; i < 10; i++)
	{
		d1.push_back(i);
	}
	d1.erase(++d1.begin());
	printDeque(d1);
	d1.erase(d1.begin(), d1.end());   //d1.clear();具有同等作用
	printDeque(d1);
}

int main() {

	test01();
	cout << endl;
	test02();
	cout << endl;
	test03();

	system("pause");

	return 0;
}

6、deque的数据存取

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

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

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

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

#include<iostream>
#include<deque>
using namespace std;

void test01()     
{
	deque<int>d1;
	for (int i = 0; i < 10; i++)
	{
		d1.push_back(i);      //尾插
		d1.push_front(i * 2); //头插
	}
	//通过[]方式访问元素
	for (int i = 0; i < d1.size(); i++)
	{
		cout << d1[i] << " ";
	}
	cout << endl;
	//通过at方式访问元素
	for (int i = 0; i < d1.size(); i++)
	{
		cout << d1.at(i) << " ";
	}
	cout << endl;
	cout << "第一个元素为:" << d1.front() << endl;
	cout << "最后一个元素为:" << d1.back() << endl;
}

int main() {

	test01();

	system("pause");

	return 0;
}

7、deque的数据排序算法

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

#include<iostream>
#include<deque>
#include<algorithm>
using namespace std;

void printDeque(const deque<int> &d)
{
	for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
	{
		cout << *it << "  ";
	}
	cout << endl;
}

void test01()     
{
	deque<int>d1;
	for (int i = 0; i < 10; i++)
	{
		d1.push_back(i);      //尾插
		d1.push_front(i * 2); //头插
	}
	printDeque(d1);
	sort(d1.begin(),d1.end());   //升序排序
	//对于支持随机访问的迭代器的容器,都可以用sort算法直接对其进行排序
	//vector容器也可以利用sort进行排序
	printDeque(d1);
}

int main() {

	test01();

	system("pause");

	return 0;
}

8、案例

(1)案例描述:有5名选手ABCDE,10个评委分别对每一名选手打分,去除最高分,去除评委中最低分,取平均分。

(2)实现步骤:

①创建五名选手,放到vector中。

②遍历vector容器,取出来每一个选手,执行for循环,可以把10个评分打分存到deque容器中。

③sort算法对deque容器中分数排序,去除最高和最低分。

④deque容器遍历一遍,累加总分。

⑤获取平均分。

(3)代码:

#include<iostream>
#include<deque>
#include<vector>
#include<algorithm>
#include<string>
#include<time.h>
using namespace std;

/* 案例描述:有5名选手ABCDE,10个评委分别对每一名选手打分,去除最高分,去除评委中最低分,取平均分
实现步骤:
创建五名选手,放到vector中
遍历vector容器,取出来每一个选手,执行for循环,可以把10个评分打分存到deque容器中
sort算法对deque容器中分数排序,去除最高和最低分
deque容器遍历一遍,累加总分
获取平均分*/

class Person
{
public:
	Person(int score, string name)
	{
		m_name = name;
		m_score = score;
	}
	int m_score;
	string m_name;
};
void createPerson(vector<Person>&v)
{
	string nameSeed = "ABCDE";
	for (int i = 0; i < 5; i++)
	{
		string name = "player_";
		name += nameSeed[i];
		int score = 0;
		Person p(score, name);
		v.push_back(p);
	}
}
void setScore(vector<Person>&v)
{
	for (vector<Person>::iterator it = v.begin(); it != v.end(); it++)
	{
		deque<int>d;
		for (int i = 0; i < 10; i++)
		{
			int score = rand() % 51 + 50;   //int score = [rand() % 51] + 50; []内取值为0~50
			d.push_back(score);
		}
		sort(d.begin(),d.end());
		d.pop_back();
		d.pop_front();
		int sum = 0;
		for (deque<int>::iterator dit = d.begin(); dit != d.end(); dit++)
		{
			sum += *dit;
		}
		int avg = sum / d.size();
		it->m_score = avg;
	}
}

void func()     
{
	vector<Person>p;
	createPerson(p);
	setScore(p);
	for (vector<Person>::iterator it = p.begin(); it != p.end(); it++)
	{
		cout << it->m_name << "的最终得分为" << it->m_score << endl;
	}
}

int main() {

	srand((unsigned int)time(NULL));
	func();

	system("pause");

	return 0;
}

五、stack容器

1、stack的基本概念

(1)stack是一种先进后出(First In Last Out,FILO)的数据结构,它只有一个出口。

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

(1)栈中进入数据的过程称为入栈(push),栈中弹出数据的过程称为出栈(pop)。

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<stack>
using namespace std;

void test01()     
{
	stack<int>s;    //符合先进后出的数据结构

	s.push(10);     //入栈
	s.push(20);
	s.push(30);
	s.push(40);

	while (!s.empty())   //只要栈不为空,查看栈顶,并执行出栈操作
	{
		cout << "栈顶元素为:" << s.top() << endl;
		s.pop();    //出栈
	}
	cout << "现在栈的大小为:" << s.size() << endl;
}

int main() {

	test01();

	system("pause");

	return 0;
}

六、queue 容器

1、queue的基本概念

(1)Queue是一种先进先出(First In First Out,FIFO)的数据结构,它有两个出口。

(2)队列容器允许从一端(队尾)新增元素,从另一端(队头)移除元素。

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

(4)数据进入队列中的过程称为入队(push),数据从队列中被移出的过程称为出队(pop)。

2、queue的常用接口

//构造函数:

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

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

//赋值操作:

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

//数据存取:

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

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

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

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

//大小操作:

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

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

#include<iostream>
#include<queue>
using namespace std;

class Person
{
public:
	int age1;
	int age2;
	Person(int age1, int age2)
	{
		this->age1 = age1;
		this->age2 = age2;
	}
};

void test01()     
{
	queue<Person>q;       //创建队列
	Person p1(10, 18);    //准备数据
	Person p2(20, 38);
	Person p3(30, 58);
	Person p4(40, 28);
	q.push(p1);           //入队
	q.push(p2);
	q.push(p3);
	q.push(p4);
	cout << "队列大小为:" << q.size() << endl;
	while (!q.empty())
	{
		cout << "队头为: age1 = " << q.front().age1 << "  age2 = " << q.front().age2 << endl;
		cout << "队尾为: age1 = " << q.back().age1 << "  age2 = " << q.back().age2 << endl;
		cout << endl;
		q.pop();          //出队
	}
	cout << "队列大小为:" << q.size() << endl;
}

int main() {

	test01();

	system("pause");

	return 0;
}

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

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

相关文章

分享58个NodeJs爬虫源码总有一个是你想要的

分享58个NodeJs爬虫源码总有一个是你想要的 学习知识费力气&#xff0c;收集整理更不易。 知识付费甚欢喜&#xff0c;为咱码农谋福利。 链接&#xff1a;https://pan.baidu.com/s/1_Im6ituI4izxP05oyA2z3Q?pwd8888 提取码&#xff1a;8888 项目名称 anyproxy 、nodejs …

【算法 - 动态规划】最长回文子序列

上篇文章中&#xff0c;我们学习一个新的模型&#xff1a; 样本对应模型&#xff0c;该模型的套路就是&#xff1a;以结尾位置为出发点&#xff0c;思考两个样本的结尾都会产生哪些可能性 。 而前篇文章中的 纸牌博弈问题 属于 [L , R]上范围尝试模型。该模型给定一个范围&…

爬虫基本库的使用(requests库的详细解析)

注&#xff1a;本文一共4万多字&#xff0c;希望读者能耐心读完&#xff01;&#xff01;&#xff01; 前面,我们了解了urllib库的基本用法&#xff08;爬虫基本库的使用(urllib库的详细解析)-CSDN博客&#xff09;。其中&#xff0c;确实又不方便的地方。例如处理网页验证…

P2670 [NOIP2015 普及组] 扫雷游戏 ---- 洛谷

题目描述 扫雷游戏是一款十分经典的单机小游戏。在 n 行 m 列的雷区中有一些格子含有地雷&#xff08;称之为地雷格&#xff09;&#xff0c;其他格子不含地雷&#xff08;称之为非地雷格&#xff09;。玩家翻开一个非地雷格时&#xff0c;该格将会出现一个数字——提示周围格子…

【前端素材】推荐优质后台管理系统Xoric平台模板(附源码)

一、需求分析 当我们从多个层次来详细分析后台管理系统时&#xff0c;可以将其功能和定义进一步细分&#xff0c;以便更好地理解其在不同方面的作用和实际运作。 1. 功能层次 a. 用户管理功能&#xff1a; 用户注册和登录&#xff1a;管理用户账户的注册和登录过程。权限管…

C#上位机与三菱PLC的通信08---开发自己的通讯库(A-1E版)

1、A-1E报文回顾 具体细节请看&#xff1a; C#上位机与三菱PLC的通信03--MC协议之A-1E报文解析 C#上位机与三菱PLC的通信04--MC协议之A-1E报文测试 2、为何要开发自己的通讯库 前面使用了第3方的通讯库实现了与三菱PLC的通讯&#xff0c;实现了数据的读写&#xff0c;对于通…

熬夜整理的考研考公学习资料,祝愿大家成功上岸

现如今大学生毕业大都在考研、考公这两条道路上选一个。今天给这些朋友同学分享一下考研、考公的学习资料。希望能够帮助到部分努力的同学&#xff01; 以下就是考研、考公的学习资料 学习资料获取地址 点击获取学习资料 就拿考研来说这里不仅包含了深入浅出的复习笔记&#x…

steam搬砖项目还能不能做,新手小白月入过万真的假的

steam搬砖项目还能不能做&#xff1f;今天&#xff0c;我们将通过实际数据来告诉你&#xff0c;当前市场上存在着大量没有实操过Steam搬砖项目的人&#xff0c;他们也开始参与其中&#xff0c;导致市场格局混乱。这些人可能是第一次接触该项目&#xff0c;但却毫不犹豫地发表自…

Facebook Horizon:探索虚拟现实中的社交空间

随着科技的不断进步&#xff0c;虚拟现实&#xff08;VR&#xff09;技术正成为社交互动和娱乐体验的新前沿。在这个数字时代&#xff0c;Facebook作为全球最大的社交媒体平台之一&#xff0c;正在引领虚拟社交的新时代&#xff0c;其推出的虚拟社交平台Facebook Horizon成为了…

如何使用Docker部署MongoDB并结合内网穿透实现远程访问本地数据库

文章目录 前言1. 安装Docker2. 使用Docker拉取MongoDB镜像3. 创建并启动MongoDB容器4. 本地连接测试5. 公网远程访问本地MongoDB容器5.1 内网穿透工具安装5.2 创建远程连接公网地址5.3 使用固定TCP地址远程访问 正文开始前给大家推荐个网站&#xff0c;前些天发现了一个巨牛的 …

Fiddler工具 — 19.Fiddler抓包HTTPS请求(二)

5、查看证书是否安装成功 方式一&#xff1a; 点击Tools菜单 —> Options... —> HTTPS —> Actions 选择第三项&#xff1a;Open Windows Certificate Manager打开Windows证书管理器。 打开Windows证书管理器&#xff0c;选择操作—>查看证书&#xff0c;在搜索…

【webrtc】m77 PacedSender

mediasoup是m77的代码,m77的代码并没有paced controller ,而且与paced sender 的逻辑混在了一起。结合大神们的代码分析,对照m77 进行 理解。m77 有ProbeController。给pacersender 更新飞行数据:PacedSender::InsertPacket(size_t bytes) 对应的是 PacingController::OnPa…

微信小程序错误----config is not defined

微信小程序出错 请求头发生错误 修改 options.header {// 为请求头对象添加 token 验证的 Authorization 字段Access-Token: token,platform: MP-WEIXIN,// 保留原有的 header...options.header,}

运维SRE-11 备份服务及备份项目

1.第一个服务-rsync备份服务-守护进程模式 1.1概述 守护进程&#xff1a;持续运行的进程&#xff0c;也可以叫作服务服务一般分为&#xff1a;服务端与客户端服务端&#xff1a;linux服务器上运行的各种服务软件客户端&#xff1a;linux中的客户端可能是一个命令&#xff0c;…

Android 11以上获取不到第三方app是否安装

开年第一篇&#xff0c;处理了一下年前的小问题。 问题&#xff1a;本地app跳转到第三方app地图进行导航&#xff0c;获取不到第三方地图是否安装。 解决&#xff1a; 1.添加包名 This can be done by adding a <queries> element in the Android manifest.在app下的…

性能全面提升!探索ONLYOFFICE最新8.0版:更快速、更强大,PDF表单编辑轻松搞定!

文章目录 PDF表单功能表单模板 屏幕朗读器功能EXCEL新增功能单变量求解图表向导数字排序 PPT 新增功能新增语言区域设置和优化插件界面 ONLYOFFICE 是由 Ascensio System SIA 推出的一款功能强大的办公套件&#xff0c;其中提供了适用于文本文档、表格以及演示文稿的在线编辑软…

Redis部署方式(一)四种部署方式介绍

redis的四种部署方式&#xff1a; Redis单机模式部署、Redis主从模式部署、Redis哨兵模式部署、Cluster集群模式部署&#xff0c;后面三种&#xff08;主从模式&#xff0c;Sentinel哨兵模式&#xff0c;Cluster模式&#xff09;也可以统称为集群模式。 一、单机 1、缺点&…

简单实现节流函数踩的小坑

平时debounce&#xff08;防抖&#xff09;用得多&#xff0c;throttle用得少&#xff0c;记下写 throttle 时遇到的低级错误。 节流&#xff0c;一定时间内多次操作&#xff0c;在最早操作的若干延迟后执行。 场景参考&#xff1a;周期上报&#xff0c;有的数据不急着报&#…

OpenWRT部署web站点并结合内网穿透实现无公网ip远程访问

文章目录 前言1. 检查uhttpd安装2. 部署web站点3. 安装cpolar内网穿透4. 配置远程访问地址5. 配置固定远程地址 前言 uhttpd 是 OpenWrt/LuCI 开发者从零开始编写的 Web 服务器&#xff0c;目的是成为优秀稳定的、适合嵌入式设备的轻量级任务的 HTTP 服务器&#xff0c;并且和…

医疗行业的数字化转型:开发智慧医疗源码与互联网医院APP教学

今天&#xff0c;笔者将与大家共同了解医疗行业的数字化转型过程&#xff0c;重点关注开发智能医疗源码以及互联网医院APP的实践指南&#xff0c;希望能够为医疗机构的数字化建设提供有益的参考和指导。 一、数字化转型背景与意义 数字化转型则可以通过智能化技术&#xff0c;…