STL中,最常用的容器之一
vector容器
vector基本概念
vector数据结构和数组非常相似,也称为单端数组
与普通数组的区别
数组是静态空间
vector可以动态扩展
动态扩展
不是在原空间后续接新空间,而是找到更大的内存空间,将原数据拷贝到新空间,释放原空间
vector容器的迭代器是支持随机访问的迭代器
vector构造函数
创建vector容器
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);//0 1 2 3 4 5 6 7 8 9
//通过区间构造
vector<int>v2(v1.begin(), v1.end());
printVector(v2);//0 1 2 3 4 5 6 7 8 9
//n个elem方式构造
vector<int>v3(10,100);
printVector(v3);//100 100 100 100 100 100 100 100 100 100
//拷贝构造,用的比较多
vector<int>v4(v3);
printVector(v4);//100 100 100 100 100 100 100 100 100 100
}
int main() {
test01();
system("pause");
return 0;
}
vector多种构造方式没有什么可比性,灵活使用即可
vector赋值操作
函数原型:
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);//0 1 2 3 4 5 6 7 8 9
//赋值
vector<int>v2;
v2 = v1;
printVector(v2);//0 1 2 3 4 5 6 7 8 9
//assign赋值
vector<int>v3;
v3.assign(v1.begin(), v1.end());
printVector(v3);//0 1 2 3 4 5 6 7 8 9
//n个elem方式赋值
vector<int>v4;
v4.assign(10, 100);
printVector(v4);//100 100 100 100 100 100 100 100 100 100
}
总结: vector赋值方式比较简单, 使用operator=, 或者assign都可以
vector容量和大小
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);//0 1 2 3 4 5 6 7 8 9
if (v1.empty()) {
cout << "v1为空" << endl;
}
else {
cout << "v1不为空" << endl;
cout << "v1容量:" << v1.capacity() << endl;//v1容量:13
cout << "v1大小:" << v1.size() << endl;//v1大小:10
}
//重新指定大小
v1.resize(15,100);//利用重载版本,可以指定默认填充值:参数2
printVector(v1);//如果重新指定的比原来的长,默认 用0填充 新位置
//0 1 2 3 4 5 6 7 8 9 100 100 100 100 100
v1.resize(5);
printVector(v1);//如果重新指定的比原来的短,超出部分被删除
//0 1 2 3 4
}
总结:
●判断是否为空 -- empty
●返回元素个数 -- size
●返回容器容量 -- capacity
●重新指定大小 -- resize
vector插入和删除
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;
v1.push_back(10);//尾插
v1.push_back(20);
v1.push_back(30);
v1.push_back(40);
v1.push_back(50);
printVector(v1);//10 20 30 40 50
v1.pop_back();//尾删
printVector(v1);//10 20 30 40
v1.insert(v1.begin(), 100);//插入 第一个参数是迭代器
printVector(v1);//100 10 20 30 40
v1.insert(v1.begin(), 2, 1000);
printVector(v1);//1000 1000 100 10 20 30 40
v1.erase(v1.begin());//删除 参数也是迭代器
printVector(v1);//1000 100 10 20 30 40
v1.erase(v1.begin(), v1.end());//清空
v1.clear();//清空
printVector(v1);//空行
}
总结:
●尾插 -- push_ back
●尾删 -- pop_ back
●插入 -- insert (位置迭代器)
●删除 -- erase (位置迭代器)
●清空 -- clear
vector数据存取
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;//第一个元素:0
cout << "最后一个元素:" << v1.back() << endl;//最后一个元素:9
}
除了用迭代器获取vector容器中元素,[ ]和at也可以
vector互换容器
实现两个容器内元素互换
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);
}
printVector(v1);//0 1 2 3 4 5 6 7 8 9
vector<int>v2;
for (int i = 10; i > 0; i--) {
v2.push_back(i);
}
printVector(v2);//10 9 8 7 6 5 4 3 2 1
cout << "交换后:" << endl;
v1.swap(v2);
printVector(v1);//10 9 8 7 6 5 4 3 2 1
printVector(v2);//0 1 2 3 4 5 6 7 8 9
}
void test02() {
vector<int>v;
for (int i = 0; i < 100000; i++) {
v.push_back(i);
}
cout << "v容量:" << v.capacity() << endl;//v容量:138255
cout << "v大小:" << v.size() << endl;//v大小:100000
v.resize(3);//重新指定大小
cout << "v容量:" << v.capacity() << endl;//v容量:138255
cout << "v大小:" << v.size() << endl;//v大小:3
//巧用swap收缩内存
vector<int>(v).swap(v);
//vector<int>(v) -- 匿名对象,被v按照目前使用的大小初始化,容量、大小都是3
//.swap(v) -- 容器交换
//匿名对象运行完后,系统会自动回收
cout << "v容量:" << v.capacity() << endl;//v容量:3
cout << "v大小:" << v.size() << endl;//v大小:3
}
swap可以使两个容器互换,可以达到实用的收缩内存效果
vector预留空间
减少vector在动态扩展容量时的扩展次数
void test01() {
vector<int>v;
v.reserve(100000);//利用reserve预留空间
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;//num = 30,预留空间后,num = 1
}
deque容器
deque容器基本概念
双端数组,可以对头端进行插入和删除操作
deque与vector区别:
- vector对于头部的插入删除效率低,数据量越大,效率越低
- deque相对而言,对头部的插入删除速度回比vector快
- vector访问元素时的速度会比deque快,这和两者内部实现有关
deque内部工作原理:
- deque内部有个中控器,维护每段缓冲区中的内容,缓冲区中存放真实数据
- 中控器维护的是每个缓冲区的地址,使得使用deque时像一片连续的内存空间
deque容器的迭代器也是支持随机访问的
deque构造函数
#include<deque>;
void printDeque(const deque<int>& d) {//防止被修改,加const变成只读,iterator也要加const
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);//0 1 2 3 4 5 6 7 8 9
deque<int>d2(d1.begin(), d1.end());
printDeque(d2);//0 1 2 3 4 5 6 7 8 9
deque<int>d3(10, 100);
printDeque(d3);//100 100 100 100 100 100 100 100 100 100
deque<int>d4(d3);
printDeque(d4);//100 100 100 100 100 100 100 100 100 100
}
deque容器和vector容器构造方式几乎一致
deque赋值操作
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);//0 1 2 3 4 5 6 7 8 9
deque<int>d2;//operator= 赋值
d2 = d1;
printDeque(d2);//0 1 2 3 4 5 6 7 8 9
//assign赋值
deque<int>d3;
d3.assign(d1.begin(), d1.end());
printDeque(d3);//0 1 2 3 4 5 6 7 8 9
deque<int>d4;
d4.assign(10, 100);
printDeque(d4);//100 100 100 100 100 100 100 100 100 100
}
deque赋值操作与vector相同
deque大小操作
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);
}
if (d1.empty()) {
cout << "d1为空" << endl;
}
else {
cout << "d1不为空" << endl;
cout << "d1大小:" << d1.size() << endl;//d1大小:10
//deque容器没有容量概念
}
//重新指定大小
//d1.resize(15);//0 1 2 3 4 5 6 7 8 9 0 0 0 0 0
d1.resize(15,1);
printDeque(d1);//0 1 2 3 4 5 6 7 8 9 1 1 1 1 1
d1.resize(5);//0 1 2 3 4
printDeque(d1);
}
- deque没有容量概念
- 判断是否为空 —— empty
- 返回元素个数 —— size
- 重新指定个数 —— resize
deque插入和删除
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;
d1.push_back(10);//尾插
d1.push_back(20);
d1.push_front(100);//头插
d1.push_front(200);
printDeque(d1);//200 100 10 20
d1.pop_back();//尾删
printDeque(d1);//200 100 10
d1.pop_front();//头删
printDeque(d1);//100 10
d1.insert(d1.begin(), 1000);//insert插入
printDeque(d1);//1000 100 10
d1.insert(d1.begin(), 2, 10000);
printDeque(d1);//10000 10000 1000 100 10
//按照区间进行插入
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 10000 10000 1000 100 10
//删除
deque<int>::iterator it = d1.begin();
it++;
d1.erase(it);
printDeque(d1);//1 3 10000 10000 1000 100 10
//d1.erase(d1.begin(),d1.end());//区间方式删除,此行相当于清空
d1.clear();//清空
printDeque(d1);
}
插入和删除提供的位置是迭代器
deque数据存取
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);
//利用[]方式访问数组元素
for (int i = 0; i < d.size(); i++) {
cout << d[i] << " ";//300 200 100 10 20 30
}
cout << endl;
//利用at方式访问元素
for (int i = 0; i < d.size(); i++) {
cout << d.at(i) << " ";//300 200 100 10 20 30
}
cout << endl;
cout << "第一个元素:" << d.front() << endl;// 第一个元素:300
cout << "最后一个元素:" << d.back() << endl;// 最后一个元素:30
}
deque排序
利用算法实现对deque容器进行排序
#include<algorithm>//算法头文件(标准算法头文件)
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);//300 200 100 10 20 30
//排序 默认排序规则,从小到大,升序
//对于支持随机访问的迭代器的容器,都可以利用sort算法直接对其进行排序
//vector容器也可以利用sort进行排序
sort(d.begin(), d.end());
cout << "排序后:" << endl;
printDeque(d);//10 20 30 100 200 300
}
sort算法非常实用,使用时包含头文件algorithm即可。
案例——评委打分
五名选手:ABCDE,10个评委分别对每一名选手打分,去除最高分,去除最低分,取平均分
实现步骤:
- 创建五名选手,放到vector中
- 遍历vector容器,取出来每一个选手,执行for循环,可以把10个评分打分存到deque容器中
- sort算法对deque容器中分数排序,去除最高和最低分
- deque容器遍历—遍,累加总分
- 获取平均分
//案例——评委打分
#include<iostream>
using namespace std;
#include<vector>//使用每一个容器都要包含头文件
#include<deque>
#include<algorithm>//算法头文件(标准算法头文件)
#include<string>
#include<ctime>
class Person {
public:
Person(string name, int score) {
this->m_Name = name;
this->m_Score = score;
}
string m_Name;
int m_Score;//平均分
};
void createPerson(vector<Person>& v) {
string nameSeed = "ABCDE";
for (int i = 0; i < 5; i++) {
string name = "选手";
name += nameSeed[i];
int score = 0;
Person p(name, score);
v.push_back(p);//将创建的person对象放入到容器
}
}
//打分
void setScore(vector<Person>& v) {
for (vector<Person>::iterator it = v.begin(); it != v.end(); it++) {
//准备一个deque容器,放评委的打分
deque<int>d;
for (int i = 0; i < 10; i++) {
int score = rand() % 41 + 60;//60~100随机数
d.push_back(score);
}
cout <<"选手:"<< it->m_Name << "\t" << "打分:" << endl;
for (deque<int>::const_iterator dit = d.begin(); dit != d.end(); dit++) {
cout << *dit << " ";
}
cout << endl;
//先排序,找到最高最低分,并去除
sort(d.begin(), d.end());
d.pop_back();
d.pop_front();
//获取平均分
int sum = 0;
for (deque<int>::const_iterator dit = d.begin(); dit != d.end(); dit++) {
sum += *dit;//累加每个评委的分数
}
int avg = sum / d.size();//计算平均分
//将平均分赋值到选手
it->m_Score = avg;
}
}
void showScore(vector<Person>& v) {
for (vector<Person>::iterator it = v.begin(); it != v.end(); it++) {
cout << "姓名:" << it->m_Name << "\t" << "平均分:" << it->m_Score << endl;
}
}
int main() {
//随机数种子
srand((unsigned int)time(NULL));
//创建5名选手
vector<Person>v;//存放选手容器
createPerson(v);
测试代码
//for (vector<Person>::iterator it = v.begin(); it != v.end(); it++) {
// cout << (*it).m_Name <<"\t" << (*it).m_Score << endl;
//}
//给选手打分
setScore(v);
//显示最后得分
showScore(v);
system("pause");
return 0;
}
stack容器
stack基本概念
一种先进后出(First In Last Out,FILO)的数据结构,只有一个出口
栈中只有顶端的元素才可以被外界使用,因此栈不允许有遍历行为
栈容器,符合先进后出
栈可以判断容器是否为空——empty,可以返回元素个数——size。
栈中进入数据称为——入栈(push)
栈中弹出数据称为——出栈(pop)
stack常用接口
栈容器常用的对外接口
#include<stack>;
void test01() {
stack<int>s;//特点:符合先进后出数据结构
s.push(10);
s.push(20);
s.push(30);
s.push(40);
cout << "栈的大小:" << s.size() << endl;//栈的大小:4
//只要栈不为空,查看栈顶,并且执行出栈操作
while (!s.empty()) {
cout << "栈顶元素为:" << s.top() << endl;
s.pop();//出栈
}
cout << "栈的大小:" << s.size() << endl;//栈的大小:0
}
queue容器
queue基本概念
一种先进先出(First In Frist Out,FIFO)的数据结构,有两个出口
判断队列是否为空——empty,返回队列大小——size。
队列queue符合先进先出,只有队头和队尾能被外界访问,因此不允许有遍历行为
队列容器允许从一端新增元素,从另一端移除元素
队列中进数据称为——入队 push
队列中出数据称为——出队 pop
queue常用接口
#include<queue>;
class Person {
public:
Person(string name, int age) {
this->m_Name = name;
this->m_Age = age;
}
string m_Name;
int m_Age;
};
void test01() {
queue<Person>q;//创建队列
//准备数据
Person p1("唐僧", 30);
Person p2("孙悟空", 1000);
Person p3("猪八戒", 900);
Person p4("沙僧", 800);
//入队
q.push(p1);
q.push(p2);
q.push(p3);
q.push(p4);
cout << "队列的大小:" << q.size() << endl;//队列的大小:4
//判断只要对列不为空,查看队头、队尾,出队
while (!q.empty()) {
cout << "队头元素——姓名:" << q.front().m_Name << "\t年龄:" << q.front().m_Age << endl;
cout << "队尾元素——姓名:" << q.back().m_Name << "\t年龄:" << q.back().m_Age << endl;
q.pop();//出队
}
cout << "队列的大小:" << q.size() << endl;//队列的大小:0
}