C++中的顺序容器

C++中的顺序容器包含有:

  • vector 可变大小的数组,一般选择是这个!
  • deque 双端队列
  • list 双向链表
  • forward_list 单向链表,没有size操作
  • array 固定大小的数组,支持随机访问,不可以添加和删除,因为这些是新标准的容器,其的性能非常的高。建议使用。
  • string 可变大小的,专门用来存储对应的字符串的

这些容器是在下面两个方面有着不同的性能折中的:

  • 向容器添加或者从容器中删除元素的代价
  • 非顺序访问容器元素的代价

  除了array外,其余的都是有着高效、灵活的内存管理。随意的添加和删除元素,扩大和收缩容器的大小。同时string和vector的实现都是将原先的元素顺序的保存在内存中的,按照元素的下标来计算其的地址是非常快速的,但是在插入和删除的时候则类似于正常的数组的操作需要移动很多的元素,非常的耗费时间, 可能我们在实际使用的时候没有注意到,但是这些都是要考虑具体的使用情况的!

  list和forward_list的设计目的就是让添加和删除元素的时候操作很快,但是其无法完成自动的随机访问。同时还有带来额外的存储空间的开销。

  其实上面的两者就是对应的数组和列表的区别问题,下面简单的列举一下数组和列表的不同的优缺点!
数组

  • 支持随机访问,内存地址空间连续,空间利用率高,但是在数组中间位置处删除和插入操作需要移动大量的元素。
  • 列表只能够顺序访问,内存地址空间不连续,内存空间的利用率也不是很高,因为需要额外的存储指针的值,但是支持在任意位置进行插入和删除操作而且不需要移动大量的元素。
  • 应该在不同的场景使用不同的方法!

每个容器的假如为C:则定义的为C.empty():意思是当其中C中存储元素的返回为false,否则返回为true。同时并不是全部的容器都支持全部的统一的操作的,很多的操作是不支持的。迭代器的范围为:[begin, end),则下面的代码是完全合法的:

while(begin != end) {
	*begin = val;
	++begin;
}
auto iter = a.begin();
auto iter2 = b.cbegin();
auto iter3 = c.rbegin();
auto iteer4 = c.crbegin();

可以直接按照下面的方式使用迭代器范围拷贝!

deque<stirng> authorCopy(author.begin(), it);
//其中it为author中的一个迭代器的值!

列表初始化:

list<string> authors = {"a", "v", "a"};
//而且还显示的定义了对应的容器的大小值!

或者还可以按照对应的使用于顺序容器大小有关的初始化

vector<int> itemm(10, -1);
//则代表初始化的为10个元素,取值都是-1.
vector<int> itemm(10);
//10个元素,其中的值都是0. 假如使用的是string的类型的话值是空的string的值!

标准库中的array具有固定的大小,在声明的时候不但要给出对应的数据类型而且还要给出对应的元素的个数值。

array<int, 42>;
aray<string. 10?;
array<int, 10> ia1;
array<int, 10> ia1 = {0,1,2,3,4,5,6,7,8,9};

赋值的时候不支持直接拷贝或者赋值,然后对应的类型匹配的时候对用的操作便是成功的!

访问容器的成员函数的时候对应的返回的结果都是引用的类型,不论是使用其中的front、back、下标、at等访问都是引用的结果。

	vector<int> item = {1, 3, 4, 5};
	auto &a = item[0];
	cout << a << endl; 
	a = 1000;
	cout << item[0] << endl; 
	//输出为:
	//1
	//1000 

插入元素是指定对应的单一的迭代器的位置后然后删除其中的值!
删除元素则是对应在一个范围内的迭代器给出来之后再删除其中的元素的值!

从容器中删除元素的方法,使用rease的方法,其中传值为迭迭代器,或者是一个迭代器,或者是两个迭代器代表一个范围,其中返回的都是最后被删除的元素之后的迭代器的地址。

list<int> lst = {0, 1, 2, 3, 4};
auto it = lst.begin();
while(it != lst.end()) 
	if(*it % 2 == 0)
		it = lst.erase(it) //当元素为奇数
	else
		++it;

上面的代码中删除的,首先都是检查元素是否为奇数,是的时候则删除元素,对应的会将其中的it的值设置为删除后面的元素的下一个迭代器的地址,所以在if的训话中不需要对于其中的迭代器的值进行更新。删除成功之后自动更新的。

list.clear();
list.erase(slit.begin(), list.end());

上面的代码完成删除全部的列表中全部的元素!
要记住的是删除元素之后其会将迭代器的值指向下一位的。
对于其中的单向列表的操作的问题上,因为其对应的元素的值是列表在操作的时候非常的特殊,所以在实现的时候需要一些特定的操作!详细的情况在后续的博客中给出!

auto begin = v.begin(),
	end = v.end();
while (begin != end ) {
	++begin;
	begin = v.insert(begin, 42);
	++begin;
}

上面的代码中因为最开始求出来的end的值对应的在插入元素之后会发生改变,这样的操作会让对应的end的迭代器失效,所以我们需要将上述的代码修改为:

while(begin != v.end()) 
//每次操作的时候都要循环一次重新求解一次!

string中的方法操作比其余的多出来很多的,其的删除或者插入新的元素的操作不但支持使用迭代器的方式同时也支持使用下标的方式完成。

int i = 42;
string s = to_string(i);
double d = stod(s); //将字符串转换为浮点数。

未完待续…

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值