STL(标准模板库)的使用

1. STL初识

1.1 STL的诞生

  • C++的面向对象和泛型编程思想,目的就是复用性的提高
  • 为了建立数据结构和算法的一套标准,诞生了STL

1.2 STL基本概念

  • STL(标准模板库)
  • STL从广义上分为:容器、算法、迭代器
  • 容器算法之间通过迭代器进行无缝连接
  • STL几乎所有的代码都采用了模板类或模板函数

1.3 STL六大组件

容器、算法、迭代器、仿函数、适配器(配接器)、空间配置器

  • 容器:各种数据结构,如vector,list,deque,set,map等,用来存放数据
  • 算法:各种常用的算法,如sort,find,copy,for_each等
  • 迭代器:扮演了容器和算法之间的胶合剂
  • 仿函数:行为类似函数,可作为算法的某种策略
  • 适配器:一种用来修饰容器或者仿函数或迭代器接口的
  • 空调配置器:负责空间的配置与管理

1.4 STL容器、算法、迭代器

容器:STL容器就是将运用最广泛的一些数据结构实现出来

常用的数据结构:数组,链表,树,栈,队列,集合,映射表等

这些容器分为 序列式容器和关联式容器 两种:

  • 序列式容器:强调值的排序,序列式容器中的每个元素都有固定的位置
  • 关联式容器:二叉树结构,各个元素之间没有严格的物理上的顺序关系

算法

有限的步骤,解决逻辑上或数学上的问题,算法可以分为质变算法和非质变算法

  • 质变算法:是指运算过程中会更改区间内的元素的内容,例如拷贝、替换、删除等

  • 非质变算法:是指运算过程中不会更改区间内的元素内容,例如查找、计数、遍历、寻找极值等

迭代器:算法和容器之间的桥梁

提供一种方法,使之能够依序访问某个容器中所含的各个元素,而又无需暴漏该容器的内部表示方式

每个容器都有自己专属的迭代器

迭代器使用非常类似于指针,初始阶段可以理解为指针

迭代器种类

种类功能支持运算
输入迭代器对数据的只读访问只读,支持 ++,==,!=
输出迭代器对数据的只写访问只写,支持 ++
前向迭代器读写操作,并能向前推进迭代器读写,支持 ++,==,!=
双向迭代器读写操作,并能向前和向后操作读写,支持++,–
随机访问迭代器读写操作,可以以跳跃的方式访问任意数据,功能最强的迭代器读写,支持++,–,[n],-n.<,>,>=,<=

常用的迭代器种类为双向迭代器和随机访问迭代器

1.5 容器算法迭代器初识

1. vector存放内置数据类型

STL中最常用的容器是vector,可以理解为数组

容器算法迭代器
vectorfor_eachvector::iterator

示例:

#include
#include	//标准算法头文件void myPrint(int val)
{cout << val << endl;
}void test01()
{//创建了一个vector容器---数组vector<int> v;//容器中插入数据 vector内置 .push_back()尾插法v.push_back(10);v.push_back(20);v.push_back(30);v.push_back(40);//通过迭代器访问容器中的数据vector<int>::iterator itBegin = v.begin();	//起始迭代器,指向容器中第一个元素vector<int>::iterator itEnd = v.end();	//结束迭代器,指向容器中最后一个元素的下一个位置//第一种遍历方式while (itBegin != itEnd){//对指针解引用cout << *itBegin << endl;itBegin++;}//第二种遍历方式for (vector<int>::iterator it = v.begin(); it != v.end(); it++){cout << *it << endl;}//第三种遍历方式	利用STL中提供的遍历算法for_each 需要导入标准算法头文件for_each(v.begin(), v.end(), myPrint);}
int main()
{test01();system("pause");return 0;
}

2. Vector存放自定义数据类型

示例:

#includeclass Person
{
public:Person(string name, int age){this->m_name = name;this->m_age = age;}string m_name;int m_age;
};//存放自定义数据类型
void test01()
{vector<Person> v;Person p1("hututu", 23);Person p2("lututu", 23);Person p3("eututu", 23);Person p4("mututu", 23);Person p5("pututu", 23);//向容器中尾插数据v.push_back(p1);v.push_back(p2);v.push_back(p3);v.push_back(p4);v.push_back(p5);//遍历容器中数据//it是Person*,解引用后是Personfor (vector<Person>::iterator it = v.begin(); it != v.end(); it++){/*cout << "姓名:" << (*it).m_name << " "<< "年龄:" << (*it).m_age << endl;*///it可以看作指针cout << "姓名:" << it->m_name << " "<< "年龄:" << it->m_age << endl;}
}//存放自定义数据类型指针
void test02()
{//容器中存放的是地址vector<Person*> v;Person p1("hututu", 23);Person p2("lututu", 23);Person p3("eututu", 23);Person p4("mututu", 23);Person p5("pututu", 23);//向容器中尾插数据v.push_back(&p1);v.push_back(&p2);v.push_back(&p3);v.push_back(&p4);v.push_back(&p5);//遍历容器//it是Person**,解引用的(*it)是Person*for (vector<Person*>::iterator it = v.begin(); it != v.end(); it++){cout << "姓名:" << (*it)->m_name << "\t" << "年龄:"<< (*it)->m_age << endl;}
}int main()
{test02();system("pause");return 0;
}

注意:

- vector<Person>::iterator it,it是Person*,解引用的(*it)是Person
- vector<Person*>::iterator it,it是Person**,解引用的(*it)是Person*

3. Vector容器嵌套容器

学习容器嵌套容器,将所有数据进行遍历输出

示例:

#includevoid test01()
{vector<vector<int>> v;//创建小容器vector<int> v1;vector<int> v2;vector<int> v3;vector<int> v4;//向小容器中添加数据for (int i = 0; i < 4; i++){v1.push_back(i + 1);v2.push_back(i + 2);v3.push_back(i + 3);v4.push_back(i + 4);}//将小容器插入到大容器中v.push_back(v1);v.push_back(v2);v.push_back(v3);v.push_back(v4);//通过大容器 将所有数据遍历一遍for (vector<vector<int>>::iterator it = v.begin(); it != v.end(); it++){//(*it)是vector类型的数据容器for (vector<int>::iterator vit = (*it).begin(); vit != (*it).end(); vit++){//*vit 是int类型的cout << *vit << " ";}cout << endl;}
}int main()
{test01();system("pause");return 0;
}
--------------------------------------------------------------------------------------
1 2 3 4
2 3 4 5
3 4 5 6
4 5 6 7
请按任意键继续. . .

2. STL-常用容器

2.1 string 容器

1. string 容器基本概念

本质

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

string和char 区别*:

  • char * 是一个指针(C中string的本质)
  • string是一个类,类内部封装了char* ,管理这个字符串,是一个char*类型的数据容器

特点

  • string内部封装了很多成员方法
  • string管理char*所分配的内存,不用担心复制越界或者取值越界等,由类内部进行负责

2. string 构造函数

构造函数原型

string();					//构建一个空的字符串
string(const char* s);	  	//使用字符串s进行初始化
string(const string& str);	//使用一个string对象初始化另一个string对象
string(int n,char c);		//使用n个字符初始化
void test01()
{string s1;	//默认构造//把c_string转化成了stringconst char* str = "nibukunwokun";string s2(str);cout << "s2=" << s2 << endl;//调用拷贝构造函数string s3(s2);cout << "s3=" << s3 << endl;string s4(6, 'a');cout << "s4=" << s4 << endl;}
int main()
{test01();system("pause");return 0;
}
-----------------------------------------------------------
s2=nibukunwokun
s3=nibukunwokun
s4=aaaaaa
请按任意键继续. . .

3. string 赋值操作

功能描述:给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赋值给当前的字符串

示例:

#includevoid test01()
{//string & operator=(const char* s);string str1;str1 = "hello world";cout << "str1= " << str1 << endl;//string & operator=(const string s);string str2;str2 = str1;cout << "str2= " << str2 << endl;//string & operator=(char  c); string str3;str3 = 'a';cout << "str3= " << str3 << endl;//string & assign(const char * s); string str4;str4.assign("hututu");cout << "str4= " << str4 << endl;string str5;str5.assign("hututu", 3);cout << "str5= " << str5 << endl;string str6;str6.assign(str5);cout << "str6= " << str6 << endl;string str7;str7.assign(10, 'a');cout << "str7= " << str7 << endl;
}int main()
{test01();system("pause");return 0;
}
------------------------------------------
str1= hello world
str2= hello world
str3= a
str4= hututu
str5= hut
str6= hut
str7= aaaaaaaaaa
请按任意键继续. . .

4. string 字符串拼接

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

函数原型

函数注释
string & opertor+=(const char* str);重载+=操作符
string & opertor+=(const char c);重载+=操作符
string & opertor+=(const string & str);重载+=操作符
string & append(const char* s);把字符串s拼接到当前字符串结尾
string & append(const char* s, int n);把字符串s的前n个字符连接到当前字符串结尾
string & append(const string &s);同string & opertor+=(const char* 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 = "我困";str1 += str2;cout << "str1=" << str1 << endl;//append函数string str3 = "hututu";str3.append(" and");cout << "str3=" << str3 << endl;str3.append(" xiaomei abdjs", 8);cout << "str3=" << str3 << endl;//str3.append(str2);//cout << "str3=" << str3 << endl;string str4 = "abcdefg";//从pos位置开始,截取n个元素str3.append(str4, 0, 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 c, int pos=0)const;查找字符c最后一次出现位置
int rfind(const char *s,int pos,int n)const;从pos查找s的前n个字符最后一次位置
string & replace(int pos, int n, const string & str);替换从pos开始n个字符为字符串str
string & replace(int pos,int n,const char *s);替换从pos开始的n字符为字符串s

示例

#includevoid test01()
{string str1 = "hututugaagag";int pos1 = str1.find("hu");if (pos1 == -1)cout << "未找到字符串" << endl;elsecout << "字符串第一次出现的位置是:" << pos1 << endl;//cout << "pos1=" << pos1 << endl;	//2//rfind//rfind是从右往左查找,find是左往右查找int pos2 = str1.rfind("hu");cout << "pos2=" << pos2 << endl;
}//替换
void test02()
{string str1 = "abcdefg";//从1号位置起,3个字符替换为1111str1.replace(1, 3, "1111");			cout << str1 << endl;		//a1111efg
}

总结

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

6. string 字符串比较

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

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

= 返回0
> 返回1
< 返回-1

函数原型

函数注释
int compare(const string &s)const;与字符串s比较
int compare(const char *s)const;与字符串s比较

示例

#includevoid test01()
{string str1 = "hello";string str2 = "hello";if (str1.compare(str2) == 0)cout << "str1==str2" << endl;else if (str1.compare(str2) == 1)cout << "str1>str2" << endl;elsecout << "str1 << endl;}

7. string 字符存取

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

函数注释
char& operator[](int n);通过[]方式取字符
char& art(int n);通过at方式获取字符

示例:

#includevoid test01()
{string str1 = "hello";//cout << "str1=" << str1 << endl;//依次输出字符串中字符//1、通过[]方式访问单个字符for (int i = 0; i < str1.size(); i++)cout << str1[i] << " ";cout << endl;//2、通过at方式访问单个字符for (int i = 0; i < str1.size(); i++)cout << str1.at(i) << " ";cout << endl;//修改单个字符str1[0] = 'a';cout << "str1=" << str1 << endl;	//str1=aellostr1.at(1) = 'a';cout << "str1=" << str1 << endl;	//str1=aallo
}

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个字符

示例:

#includevoid test01()
{string str = "hello";//插入str.insert(1, "111");cout << "str=" << str << endl;		//str=h111ello//删除str.erase(1, 3);cout << "str=" << str << endl;		//str=hello
}

9. string 子串获取

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

函数原型

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

示例

#includevoid test()
{string str = "abcdefg";string subStr = str.substr(1, 3);cout << subStr << endl;		//bcd
}
void test02()
{string email = "nibukunwokun@sina.com";//从邮件地址中获取用户信息int pos = email.find("@");	//返回@的下标地址string userName = email.substr(0, pos);cout << userName << endl;		//nibukunwokun
}

2.2 vector 容器

1. vector 基本概念

功能

  • vector数据容器和数组相似,也称为单端数组

vector与普通数组的区别

  • 不同指出在于数组是静态空间,而vector可以动态扩展

动态扩展

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

  • vector容器的迭代器是支持随机访问的迭代器

2. vector 构造函数

功能描述

  • 创建vector容器

函数原型

函数原型注释
vector v;采用模板实现类实现,默认构造函数
vector v(v.begin(), v.end()) ;将v [begin(),end()) 区间(前闭后开)中的元素拷贝到自身
vector v(n, elem);构造函数将n个elem拷贝给本身
vector v(const vector &vec);拷贝构造函数

示例

#includevoid 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);//n个elem方式构造vector<int>v3(10, 88);printVector(v3);//拷贝构造vector<int>v4(v3);printVector(v4);
}
-----------------------------------------------------
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
88 88 88 88 88 88 88 88 88 88
88 88 88 88 88 88 88 88 88 88
请按任意键继续. . .

3. vector 赋值操作

功能描述

  • 给vector容器进行赋值

函数原型

函数原型注释
vector& operator=(const vector &vec);重载等号操作符
assign(beg, end);将[beg,end]区间中的数据拷贝赋值给本身
assign(n, elem);将n个elem拷贝赋值给本身

示例

#include
void test01()
{vector<int> v1;for (int i = 0; i < 10; i++)v1.push_back(i);printVector(v1);//赋值 重载=vector<int> v2;v2 = v1;printVector(v2);//assignvector<int>v3;v3.assign(v1.begin(), v1.end());printVector(v3);vector<int>v4;v4.assign(10, 88);printVector(v4);
}
-----------------------------------------------
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
88 88 88 88 88 88 88 88 88 88
请按任意键继续. . .

4. vector 容量和大小

功能描述

  • 对vector容器的容量和大小操作

函数原型

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

示例

void test01()
{vector<int>v1;for (int i = 0; i < 10; i++)v1.push_back(i);printVector(v1);//.empty()为true,则代表容器为空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);v1.resize(5);printVector(v1);
}
-----------------------------------------------
0 1 2 3 4 5 6 7 8 9
v1不为空
v1的容量是:13
v1的大小是:10
0 1 2 3 4 5 6 7 8 9 0 0 0 0 0
0 1 2 3 4
请按任意键继续. . .

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();删除容器中所有元素

示例:

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(), 88);printVector(v1);v1.insert(v1.begin(), 2, 99);printVector(v1);//删除 参数也是迭代器v1.erase(v1.begin());printVector(v1);v1.erase(v1.begin(), v1.end());		//类似于 .clear()printVector(v1);
}
-----------------------------------
10 20 30 40 50
10 20 30 40
88 10 20 30 40
99 99 88 10 20 30 40
99 88 10 20 30 40请按任意键继续. . .

6. vector 数据存取

功能描述:

  • 对vector中的数据的存取操作

函数原型:

函数注释
at(int idx);返回索引idx所指的数据
operator[];返回索引idx所指的数据
front();返回容器中第一个数据元素
back();返回容器中最后一个数据元素

示例:

void test01()
{vector<int> v1;for (int i = 0; i < 10; i++)v1.push_back(i);//利用重载[]来访问vector中元素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;
}
-------------------------------------------
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
第一个元素为:0
最后一个元素为:9
请按任意键继续. . .

7. vector 互换容器

功能描述

  • 实现两个容器内元素进行互换

函数原型

函数注释
swap(vec);将vec与本身的元素互换

示例

#includevoid 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);vector<int>v2;for (int i = 10; i > 0; i--)v2.push_back(i);cout << "交换前:" << endl;printVector(v1);printVector(v2);cout << "交换后:" << endl;v1.swap(v2);printVector(v1);printVector(v2);
}//实际用途:巧用swap可以收缩内存空间
void test02()
{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;//使用swap来收缩内存/*vector(v) 匿名对象,按照v对其进行初始化.swap(v) 类似于指针的交换,相当于将匿名对象容器和v进行交换因为匿名对象由编译器自动回收,所以不用担心大量空间被占用*/vector<int>(v).swap(v);	cout << "v的容量:" << v.capacity() << endl;cout << "v的大小:" << v.size() << endl;
}
----------------------------------------------
v的容量:138255
v的大小:100000
v的容量:138255
v的大小:3
v的容量:3
v的大小:3
请按任意键继续. . .

8. vector 预留空间

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

函数原型:

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

示例:

#includevoid test01()
{vector<int> v;//利用reserve来预留空间//当数据量很大时,最开始就进行预留空间就可以避免后期不断开辟新空间v.reserve(10000);int num = 0;int *p = NULL;for (int i = 0; i < 10000; i++){v.push_back(i);//每次开辟内存时,首地址都会发生改变,用num记录动态扩展的次数if (p != &v[0]){p = &v[0];num++;}}cout << "num=" << num << endl;
}

2.3 deque容器

1. deque容器基本概念

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

deque与vector的区别

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

deque内部工作原理

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

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

  • deque容器的迭代器也是支持随机访问的

2. deque构造函数

功能描述:deque容器构造

函数原型

函数原型注释
deque deque T;默认构造形式
deque(beg,end);构造函数将【beg,end)区间中的元素拷贝给本身
deque(n, elem);构造函数将n个elem拷贝给本身
deque(cosnt deque &deq);拷贝构造函数

示例

#include//输入参数 const限定只读
void printDeque(const deque<int> &d)
{//获取迭代器deque::const_iterator类型同样也是限定只读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);deque<int> d2(d1.begin(), d1.end());printDeque(d2);deque<int>d3(10, 100);printDeque(d3);deque<int>d4(d3);printDeque(d4);
}

总结:deque容器和vector容器的构造方式几乎一致

3. deque赋值操作

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

函数原型

函数原型注释
deque& operator =(const deque &deq);重载等号操作符
assign(beg,end);将【beg, end)区间中的数据拷贝赋值给本身
assign(n, elem);将n个elem拷贝赋值给本身

示例

#includevoid printDeque(const deque<int> &d);
void test01()
{deque<int> d1;for (int i = 0; i < 10; i++)d1.push_back(i);printDeque(d1);//重载 = deque<int>d2;d2 = d1;printDeque(d2);deque<int>d3;d3.assign(d1.begin(), d1.end());printDeque(d3);deque<int>d4;d4.assign(10, 8);printDeque(d4);
}--------------------------------
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
8 8 8 8 8 8 8 8 8 8

4. deque大小操作

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

函数原型

函数原型注释
deque.empty();判断容器是否为空
deque.size();返回容器中元素的个数
deque.resize(num);重新指定容器的长度为num,若容器变长,则以默认值填充新位置;若容器变短,则末尾超出容器长度的元素被删除。
deque.resize(num, elem);重新指定容器的长度为num,若容器变长,则以elem重新填充新位置;若容器变短,则末尾超过容器长度的元素被删除。

示例

void test01()
{deque<int> d1;for (int i = 0; i < 10; i++)d1.push_back(i);printDeque(d1);if (d1.empty())cout << "d1为空" << endl;else{cout << "d1不为空" << endl;//deque没有容量的概念,因为可以无限放数据cout << "d1大小为:" << d1.size() << endl;}//重新指定大小d1.resize(15, 88);printDeque(d1);d1.resize(5);printDeque(d1);	
}
-----------------------------------------
0 1 2 3 4 5 6 7 8 9
d1不为空
d1大小为:10
0 1 2 3 4 5 6 7 8 9 88 88 88 88 88
0 1 2 3 4
请按任意键继续. . .

总结

  • deque没有容量的概念
  • 判断是否为空 - empty
  • 返回元素个数 - size
  • 重新指定个数 - resize

5. deque插入和删除

功能描述:向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位置的数据,返回下一个数据的位置

示例

void test01()
{deque<int>d1;//尾插d1.push_back(10);d1.push_back(20);//头插d1.push_front(100);d1.push_front(200);printDeque(d1);//尾删d1.pop_back();printDeque(d1);//头删d1.pop_front();printDeque(d1);
}
----------------------
200 100 10 20
200 100 10
100 10
请按任意键继续. . .
void test02()
{deque<int>d1;d1.push_back(10);d1.push_back(20);d1.push_front(100);d1.push_front(200);printDeque(d1);//insert插入d1.insert(d1.begin(), 88);printDeque(d1);d1.insert(d1.begin(), 2, 88);printDeque(d1);//按照区间进行插入deque<int>d2;d2.push_back(1);d2.push_back(2);d2.push_back(3);d1.insert(d1.begin(), d2.begin(), d2.end());printDeque(d1);	//1 2 3 88 88 88 200 100 10 20
}
-----------------------
200 100 10 20
88 200 100 10 20
88 88 88 200 100 10 20
1 2 3 88 88 88 200 100 10 20
请按任意键继续. . .
void test03()
{deque<int>d1;d1.push_back(10);d1.push_back(20);d1.push_front(100);d1.push_front(200);printDeque(d1);//删除//d1.erase(d1.begin());deque<int>::iterator it = d1.begin();it++;	//迭代器向后偏移一位,完成删除第二个元素的作用d1.erase(it);printDeque(d1);//按照区间删除d1.erase(d1.begin(), d1.end());	//相当于d1.clear()printDeque(d1);
}
---------------------------
200 100 10 20
200 10 20请按任意键继续. . .

6. deque数据存取

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

函数原型

函数原型注释
at(int idx);返回索引idx所指的数据
operator[];返回索引idx所指的数据
front();返回容器中第一个数据元素
back();返回容器中最后一个数据元素

示例

void test01()
{deque<int>d;d.push_back(10);d.push_back(20);d.push_back(30);d.push_front(8);d.push_front(88);d.push_front(888);//通过[]方式访问元素for (int i = 0; i < d.size(); i++){cout << d[i] << " ";}cout << endl;	//888 88 8 10 20 30//通过at方式访问元素for (int i = 0; i < d.size(); i++){cout << d.at(i) << " ";}cout << endl;	//888 88 8 10 20 30cout << "第一个元素为:" << d.front() << endl;cout << "最后一个元素为:" << d.back() << endl;
}

7. deque排序

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

算法

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

示例

#include	//标准算法头文件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>d;d.push_back(10);d.push_back(20);d.push_back(30);d.push_front(100);d.push_front(200);d.push_front(300);//打印printDeque(d);sort(d.begin(),d.end());cout << "排序后结果:" << endl;printDeque(d);
}
------------------------
300 200 100 10 20 30
排序后结果:
10 20 30 100 200 300
请按任意键继续. . .

总结:对于支持随机访问的迭代器的容器,都可以利用sort算法直接对其排序,eg:vector

2.4 stack容器

1.基本概念

stack是一种先进后出(FILO)的数据结构,它只有一个出口

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

入栈:栈中进入数据push

出栈:弹出数据pop

2. 常见接口

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

构造函数:

函数注释
stack stk;stack采用模板类实现,stack对象的默认构造形式
stack(const stack &stk);拷贝构造函数

赋值操作:

函数注释
stack& operator = (const stack &stk);重载等号操作符

数据存取:

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

大小操作:

函数注释
empty();判断栈顶是否为空
size();返回栈的大小

示例:

using namespace std;void test01()
{stack<int>s;//入栈s.push(10);s.push(20);s.push(30);s.push(40);cout << "栈的大小为:" << s.size() << endl;//只要栈不为空,查看栈顶并且执行出栈操作while (!s.empty()){cout << "栈顶元素为:" << s.top() << endl;//出栈s.pop();}cout << "栈的大小为:" << s.size() << endl;
}-------------------
栈的大小为:4
栈顶元素为:40
栈顶元素为:30
栈顶元素为:20
栈顶元素为:10
栈的大小为:0
请按任意键继续. . .

2.5 queue容器

1. 基本概念

  • queue是 一种先进先出(FIFO)的数据结构,它有两个出口

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

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

  • 入队:队列中进数据push

    出队:队列中出数据pop

2. queue常用接口

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

构造函数:

函数注释
queue que;queue采用模板类实现,queue对象的默认构造形式
queue(const queue &que);拷贝构造函数

赋值操作:

函数注释
queue& operator = (const queue &que);重载等号操作符

数据存取:

函数注释
push(elem);往队尾添加元素
pop();从队头移除第一个元素
back();返回最后一个元素
front();返回第一个元素

大小操作:

函数注释
empty();判断栈是否为空
size();返回栈的大小

示例:

using namespace std;class Person
{
public:Person(string name, int age){this->m_name = name;this->age = age;}string m_name;int age;
};
void test01()
{//创建队列容器queue<Person>q;Person p1("楚子航", 23);Person p2("夏弥", 21);Person p3("凯撒", 25);Person p4("诺诺", 22);//入队q.push(p1);q.push(p2);q.push(p3);q.push(p4);//判断只要队列不为空,查看队头,查看队尾,出队while (!q.empty()){cout << "队头姓名:" << q.front().m_name << "年龄:" << q.front().age << endl;cout << "队尾姓名:" << q.back().m_name << "年龄:" << q.back().age << endl;//出队q.pop();}cout << "队列的大小:" << q.size() << endl;
}
---------------------------
队头姓名:楚子航        年龄:23
队尾姓名:诺诺  年龄:22
队头姓名:夏弥  年龄:21
队尾姓名:诺诺  年龄:22
队头姓名:凯撒  年龄:25
队尾姓名:诺诺  年龄:22
队头姓名:诺诺  年龄:22
队尾姓名:诺诺  年龄:22
队列的大小:0
请按任意键继续. . .

2.6 list容器

1. 基本概念

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

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

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

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

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

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

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

list优缺点

  • 优点:

    • 可以对任意位置进行快速插入或删除元素
    • 采用动态存储分配,不会造成内存浪费和溢出
  • 缺点:

    • 容器遍历速度没有数组快;占用的空间比数组大(因为多出来指针域)

2. list构造函数

功能描述:创建list容器

函数原型注释
list lst;list采用模板类实现对象的默认构造形式
list;构造函数将【beg, end) 区间中的元素拷贝给本身
list(n,elem);构造函数将n个elem拷贝给本身
list(const list &lst);拷贝构造函数

示例

void printList(const list<int> &L)
{for (list<int>::const_iterator it = L.begin(); it != L.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_back(40);//遍历容器printList(L1);//区间方式构造list<int>L2(L1.begin(), L1.end());printList(L2);//拷贝构造list<int>L3(L1);printList(L3);list<int>L4(8, 88);printList(L4);
}
----------------------------
10 20 30 40
10 20 30 40
10 20 30 40
88 88 88 88 88 88 88 88
请按任意键继续. . .

3. list赋值和交换

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

函数原型

函数原型注释
assign(beg, end);将[beg,end)区间中的数据拷贝赋值给本身
assign(n, elem);将n个elem拷贝赋值给本身
list & operator = (const list &lst);重载等号操作符
swap(lst);将list与本身的元素互换

示例

void test01()
{list<int>L1;L1.push_back(10);L1.push_back(20);L1.push_back(30);L1.push_back(40);printList(L1);list<int>L2;L2 = L1;printList(L2);list<int>L3;L3.assign(L2.begin(), L2.end());printList(L3);list<int>L4;L4.assign(8, 88);printList(L4);
}//交换
void test02()
{list<int>L1;L1.push_back(10);L1.push_back(20);L1.push_back(30);L1.push_back(40);list<int>L2;L2.assign(8, 88);cout << "交换前:" << endl;printList(L1);printList(L2);L1.swap(L2);cout << "交换后:" << endl;printList(L1);printList(L2);
}
-----------------
交换前:
10 20 30 40
88 88 88 88 88 88 88 88
交换后:
88 88 88 88 88 88 88 88
10 20 30 40
请按任意键继续. . .

4. list大小操作

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

函数原型

函数原型注释
size();返回容器中元素的个数
empty();判断容器是否为空
resize(num);重新指定容器的长度为num,若容器变长,则以默认值重新填充新位置,如果容器变短,则末尾超出容器长度的元素被删除
resize(num, elem);重新指定容器的长度为num,若容器变长,则以elem值填充新位置,若容器变短,则末尾超出容器长度的元素被删除

示例

void test01()
{list<int>l1;l1.push_back(10);l1.push_back(20);l1.push_back(30);l1.push_back(40);printList(l1);//判断容器是否为空if (l1.empty()){cout << "l1为空" << endl;}else{cout << "l1不为空" << endl;cout << "l1中元素个数为:" << l1.size() << endl;}//重新指定大小l1.resize(10);printList(l1);l1.resize(2);printList(l1);
}
---------
10 20 30 40
l1不为空
l1中元素个数为:4
10 20 30 40 0 0 0 0 0 0
10 20
请按任意键继续. . .

5. list插入和删除

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

函数原型

函数原型注释
push_back(elem);在容器尾部加入一个元素
push_back( );删除容器中最后一个元素
push_front(elem);在容器开头插入一个元素
push_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 test01()
{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);printList(L);//尾删L.pop_back();printList(L);	//300 200 100 10 20//头删L.pop_front();printList(L);	//200 100 10 20//insert插入L.insert(L.begin(), 88);printList(L);	//88 200 100 10 20list<int>::iterator it = L.begin();L.insert(++it, 8888);printList(L);	//88 8888 200 100 10 20//删除it = L.begin();L.erase(it);printList(L);	//8888 200 100 10 20//移除L.push_back(10000);L.push_back(10000);L.push_back(10000);printList(L);	//8888 200 100 10 20 10000 10000 10000L.remove(10000);printList(L);	//8888 200 100 10 20L.clear();printList(L);
}

6. list数据存取

功能描述:对list容器数据进行存取

函数原型

函数原型注释
front();返回第一个元素
back();返回最后一个元素

示例

void test01()
{listL1;L1.push_back(10);L1.push_back(20);L1.push_back(30);L1.push_back(40);//不可以用中括号和at()方式访问list容器中的元素、//原因是因为list本质是链表,不是用连续性空间存储数据,迭代器也不支持随机访问cout << "第一个元素是:" << L1.front() << endl;cout << "最后一个元素是:" << L1.back() << endl;
}

7. list反转和排序

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

函数原型:

函数原型注释
reverse();反转排序
sort();链表排序

示例:

void printList(const list<int>&L) 
{for (list<int>::const_iterator it = L.begin(); it != L.end(); it++){cout << *it << " ";}cout << endl;
}//提供sort重载函数
bool myCompare(int v1,int v2)
{//降序:就让第一个数>第二个数return v1 > v2;
}void test01()
{list<int>L1;L1.push_back(20);L1.push_back(50);L1.push_back(40);L1.push_back(30);L1.push_back(220);L1.push_back(1);cout << "反转前:";printList(L1);//反转后cout << "反转后:";L1.reverse();printList(L1);//排序//不支持随机访问迭代器的容器,内部会支持对应的一些算法cout << "排序后:";L1.sort();	//默认升序printList(L1);cout << "降序:";L1.sort(myCompare);printList(L1);
}
----------------------
反转前:20 50 40 30 220 1
反转后:1 220 30 40 50 20
排序后:1 20 30 40 50 220
降序:220 50 40 30 20 1
请按任意键继续. . .

8. 排序案例

案例描述:将Person自定义数据类型进行排序,Person属性中有姓名,年龄,身高

排序规则:按照年龄进行升序,如果年龄相同则按照身高排序

示例:

class Person
{
public:Person(string name, int age, int height){this->m_name = name;this->m_age = age;this->m_height = height;}string m_name;int m_age;int m_height;
};//指定排序规则
bool myCompare(Person &p1,Person &p2)
{//年龄相同,按照身高进行降序if (p1.m_age == p2.m_age){return p1.m_height > p2.m_height;}else{//按照年龄升序return p1.m_age < p2.m_age;}
}
void test01()
{list<Person> L;Person p1("楚子航", 22, 188);Person p2("夏弥", 21, 168);Person p3("凯撒", 24, 192);Person p4("诺诺", 23, 171);Person p5("绘梨衣", 19, 165);Person p6("路明非", 22, 183);//向容器中插入数据L.push_back(p1);L.push_back(p2);L.push_back(p3);L.push_back(p4);L.push_back(p5);L.push_back(p6);cout << "排序前:" << endl;for (list<Person>::iterator it = L.begin(); it != L.end(); it++){cout << "姓名:" << (*it).m_name << " "<< "\t年龄:" << (*it).m_age << " "<< "\t身高:" << (*it).m_height << endl;}cout << "排序后:" << endl;L.sort(myCompare);for (list<Person>::iterator it = L.begin(); it != L.end(); it++){cout << "姓名:" << (*it).m_name << " "<< "\t年龄:" << (*it).m_age << " "<< "\t身高:" << (*it).m_height << endl;}
}
-----------------------
排序前:
姓名:楚子航    年龄:22        身高:188
姓名:夏弥      年龄:21        身高:168
姓名:凯撒      年龄:24        身高:192
姓名:诺诺      年龄:23        身高:171
姓名:绘梨衣    年龄:19        身高:165
姓名:路明非    年龄:22        身高:183
排序后:
姓名:绘梨衣    年龄:19        身高:165
姓名:夏弥      年龄:21        身高:168
姓名:楚子航    年龄:22        身高:188
姓名:路明非    年龄:22        身高:183
姓名:诺诺      年龄:23        身高:171
姓名:凯撒      年龄:24        身高:192
请按任意键继续. . .


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部