复试上机指南C++STL(二)

11 篇文章 0 订阅
11 篇文章 0 订阅

关于本文

这一篇主要介绍序列容器(vector、deque、list、array),会在每种序列容器介绍开始前,说明一下优点以及和其他三种的对比和使用场景

array

这个就不详细展开说了,说白了就是一个数组,详情参考下面这篇博客,博主写的很详细,点我看array。

vector

1.1 是什么

vector和array相似,其区别在于vector 的大小可以自动增长,从而可以包含任意数量的元素,只要元素个数超出 vector 当前容量,就会自动分配更多的空间。其只能在容器尾部高效地删除或添加元素,在其他地方进行插入删除操作可能会非常慢,只要不是特殊情况,我们都会选择vector来进行操作。

1.2 为什么

可变大小数组。支持快速随机访问。在尾部插入数据元素非常快。

1.3 常用的操作

1.3.1 初始化

下面是一个生成存放 double 型元素的 vector示例:

vector<double> values;

这些个容器的初始化都是这么个套路(为的是快速上手,如果想细细地研究原理的话,可以先参考其他博主的博文,有时间慢慢更),大家使用多了就上手了。

1.3.2 插入、遍历等常用操作
插入

1.因为容器中没有元素,所以没有分配空间,当添加第一个数据项时,会自动分配内存。可以像下面这样通过调用 reserve() 来增加容器的容量:

values.reserve(20);

注意:不是reverse反转函数,千万别拼错了,我就是因为念的顺嘴,写了个reverse。
这样就设置了容器的内存分配,至少可以容纳 20 个元素。如果当前的容量已经大于或等于 20 个元素,那么这条语句什么也不做。调用 reserve() 并不会生成任何元素。values 容器这时仍然没有任何元素,直到添加了 20 个元素后,才会分配更多的内存。调用 reserve() 并不会影响现有的元素。当然,如果通过调用 reserve() 来增加内存,任何现有的迭代器,例如开始迭代器和结束迭代器,都会失效,所以需要重新生成它们。 所以还是要充分发挥可变长度数组的优势。

2.循环进行插入元素,并输出。

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

void show(vector<int> values){
	int i;
	for(i=0;i<values.size();i++){ //可以使用迭代器vector<int>::iterator it;来进行遍历。
		cout<<values[i]<<" ";
	}
	cout<<endl;
}
int main(){
	int a;
	vector<int> v;
	while(cin>>a){
		if(a==0)
			break;
		else
			v.push_back(a);//循环向vector中添加元素,相当于栈,把元素压入栈。
	}
	show(v);
	return 0;
}
遍历

上面的输出使用的,一般性的数组的循环输出的方式,我们还可以使用迭代器进行输出,比如:

	vector<int> values)
	vector<int>::iterator it;
	for(it=values.begin();it!=values.end();it++){
		cout<<*it<<" ";
	}

效果是一样的。

常用操作

下面利用代码+注释,介绍一些vector常用的方法。

	v.insert(v.begin()+2,10);//在第二个元素后面插入10,begin表示的是第一个元素要和数组的a[0]区分开。
	v.insert(c.begin()+1, 2, vla);//从第二个位置开始,连续插入两个元素
	v.insert(c.begin()+2, c.begin(), c.end() - 1);//从第三个位置开始,连续插入第一个位置到最后一个位置之间的元素
	cout<<v[2]<<endl;//输出第三个元素,v[0]、v[1]、v[2]。
	v.erase(v.begin()+1);//删除第二个元素
	v.erase(v.begin()+1,v.end()+3);//删除区间[1,3-1]之间的元素,区间从0开始。
	v.size();//vector的大小。
	v.clear();//清空vector。
	v.begin();//返回第一个元素的迭代器。
	v.front();//返回第一个元素。
	v.end();//返回最后一个元素的迭代器。
	v.back();//返回最后一个元素。
	swap(v,v1);//交换两个vector的内容,前提是这两个vector的元素类型必须相同。
	v.pop_back();//弹出最后一个元素。

这里面还有一个点比较有用,今天做题遇到的,就是vector种的pair,也是一个键值对,操作比较方便。把题和代码贴出来,大家有兴趣的可以试一下。
在这里插入图片描述

#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
using namespace std;
typedef struct Student{
	string name;
	int no;//学号
	vector<float> score;
}student;

student s[10001];
vector<pair<int,int> > fail_stu;//pair键值,其中第一个表示的是学生的数组下标,第二个表示的是挂的科目数
bool cmp(pair<int,int>a,pair<int,int>b){
	return a.second>b.second;
}

int main(){
	int i,j,cnt=0;
	float scor;
	cout<<"请输入姓名、学号、成绩:"<<endl;
	while(cin>>s[cnt].name){
		if(s[cnt].name == "0"){	
			break;
		}
		cin>>s[cnt].no;
		while(cin>>scor){
			if(scor == -1)
				break;
			s[cnt].score.push_back(scor);
		}
		cout<<s[cnt].score[1]<<endl;
		cnt++;
		cout<<"请继续输入,按ctrl+z结束输入:"<<endl;
	}
	cout<<"不及格课程大于两门的学生的学号及平均分:"<<endl;
	for(i=0;i<cnt;i++){
		//fail_stu.clear();
		int flag=0;
		float total=0,avg=0;
		for(j=0;j<s[i].score.size();j++){
			if(s[i].score[j]<60.0)
				flag++;
			total+=s[i].score[j];
		}
		fail_stu.push_back(make_pair(i,flag));
		if(flag > 2){
			avg=total/s[i].score.size();
			cout<<s[i].no<<":"<<avg<<endl;
		}
	}
	cout<<"按照不及格课程数来排序:"<<endl;
	sort(fail_stu.begin(),fail_stu.end(),cmp);
	for(i=0;i<fail_stu.size();i++){
		cout<<s[fail_stu[i].first].no<<":"<<fail_stu[i].second<<endl;
	}
	return 0;
}

大家上代码实操就会懂的。

deque

1.1 是什么

它以双端队列的形式组织元素。可以在容器的头部和尾部高效地添加或删除对象,这是它相对于 vector 容器的优势。当需要这种功能时,可以选择这种类型的容器。
无论何时,当应用包含先入先出的事务处理时,都应该使用 deque 容器。处理数据库事务或模拟一家超市的结账队列,像这两种应用都可以充分利用 deque 容器。

1.2 为什么

双端队列。支持快速快速访问。在头尾位置插入/删除速度很快,主要就是头、尾插入,设想输入1、输出1,输入2、输出2 1,输入3、输出3 2 1;就是类似这种操作的时候可以用deque。

1.3 常用的操作

1.3.1 初始化

直接使用默认的构造器初始化,其中没有任何元素。

deque<int> a_deque;

可以在初始化的时候规定元素的个数。

deque<int> my_deque(10);

可以直接给定元素值。

deque<string> words { "one", "none", "some", "all", "none","most", "many” };
1.3.2 插入、遍历等常用操作
插入

插入分为头插、尾插:

deque<string> dec;
dec.push_back("hello");   //尾部插入
dec.push_front("world");  //头部插入

除了和 vector —样都有 emplace_back() 函数外,deque 还有成员函数 emplace_front(),可以在序列的开始位置生成新的元素。和 vector 一样,也可以使用 emplace() 或 insert() 在 deque 内部添加或移除元素。这个过程相对要慢一些,因为这些操作需要移动现有的元素。
关于 vector 容器的所有 insert() 函数也同样适用于 deque 容器。

遍历

遍历访问和vector差不多,基本一样。这里说一下deque支持[]以及可以使用deque.at(元素的下标)来访问元素。

常用操作
dec.pop_back();  //尾部删除
dec.pop_front();  //头部删除
    
//erase操作
dec.erase(dec.begin());
dec.erase(dec.end()-3, dec.end());
dec.back();  //返回最后一个元素
dec.front();  //返回第一个元素
dec.empty();  //判断是否为空
 
//调整容器大小,不足以参数2补充
dec.resize(5);
dec.resize(5,"hello");
  
dec.size();  //容器大小
deque<string> s_dec;
swap(s_dec, dec);  //交换容器内容
s_dec.swap(dec);   //交换容器内容
dec.clear();  //清空

//反序输出
deque<string>::reverse_iterator rit;
for(rit = dec.rbegin(); rit != dec.rend(); ++rit)
{
    cout<<*rit<<endl;
}

list

1.1 是什么

list容器模板定义在 list 头文件中,是某一类型对象的双向链表。

1.2 为什么

ist 容器具有一些 vector 和 deque 容器所不具备的优势,它可以在常规时间内,在序列已知的任何位置插入或删除元素。这是我们使用 list,而不使用 vector 或 deque 容器的主要原因。

1.3 常用的操作

1.3.1 初始化

list 容器的构造函数的用法类似于 vector 或 deque 容器。下面这条语句生成了一个空的 list 容器:

list<string> words;

可以创建一个带有给定数量的默认元素的列表:

list<string> sayings {20};

生成一个包含给定数量的相同元素的列表:

list<double> values(50, 3.14159265);

list 容器有一个拷贝构造函数,因此可以生成一个现有 list 容器的副本:

list<double> save_values {values};

可以用另一个序列的开始和结束迭代器所指定的一段元素,来构造 list 容器的初始化列表:

list<double> samples {++cbegin(values), --cend(values)};
1.3.2 插入、遍历等常用操作

关于常用操作这个博主写的非常详细
等遇到list的问题我再详细更list。

最后关于容器的选择
  1. 强调快速随机访问。则vector要比list好得多 。
  2. 已知要存储元素的个数。vector 好于list。
  3. 强调增删且不要在两端插入修改元素。则list显然要比vector好。
  4. 除非我们需要在容器首部插入和删除元素,deque好于vector。因为vector仅仅在尾部增删快速。
  5. 如果只需要在读取输入时在容器的中间位置插入元素,然后需要随机访问元素,则可考虑输入时将元素读入到一个List容器,然后排序,然后将排序后的list容器复制到一个vector容器中。
  6. 如果只在容易的首部和尾部插入数据元素,则选择deque.
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

li_jeremy

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

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

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

打赏作者

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

抵扣说明:

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

余额充值