C++ Primer笔记5_STL之顺序容器

1.STL(Standard Template Library)

标准模板库。从根本上说,STL是一些“容器”的集合,这些“容器”有list,
vector,set,map等,STL也是算法和其它一些组件的集合。这里的“容器”和算法的集合指的是世界上很多聪明人很多年的杰作。每一个C++程序员都应该好好学习STL。大体上包括container(容器)、algorithm(算法)和iterator(迭代器),容器和算法通过迭代器可以进行无缝连接。

2.顺序容器:

2.1顺序容器类型:

vector      可变大小数组。支持快速随机访问。在尾部之外的位置插入/删除元素速度可能很慢。

deque        双端队列。支持快速随机访问。在头尾插入/删除元素速度很快。

list       双向链表。只支持双向顺序访问。在list任何位置插入/删除速度都很快。

string       与vector类似。

*forward_list 单向链表。只支持单向顺序访问。在list任何位置插入/删除速度都很快。

*array        固定大小数组。array与forward_list是C++新标准增加的类型

如果程序要求随机访问元素,应使用vector或deque;

如果要求程序能快速的在中间插入和删除,应使用list或forward_list;

如果程序要求在头尾位置插入或删除元素,但不会在中间插入或删除,使用deque;

2.2初始化方式:

以vector为例:

vector<int> v;
vector<int> v1(v);
vector<int> v(10);//10个元素,都为0
vector<int> v(10, 1);//10个元素,都为1
vector<int> v{1, 2, 3};//  C++11中支持
vector<int> v = {1, 2, 3};// C++11中支持
#include <iostream>
#include <vector>
using namespace std;

int main()
{
	string s;
	vector<string> vecStr;

	while(cin >> s)
	{
		vecStr.push_back(s);
	}
	for(vector<string>::const_iterator i = vecStr.begin(); i!=vecStr.end(); i++)
	{
		cout << *i << endl;
	}

	return 0;
}

定义一个list对象,元素类型是int的deque:

list<deque<int> > l;

注意:

1)所有的容器基本都支持insert(插入)、erase(删除)、clear(清除)操作。

2)当用一个对象初始化容器时,或将一个对象插入到容器时,实际放入容器中的是一个值的拷贝。不是对象本身。

就像将一个对象传递给非引用的函数参数一样。随后对容器中的对象做任意改变都不会影响到原始对象。

2.3顺序容器操作:

添加元素:

c.pusk_back(t) 在c尾部加入元素t——list、deque、vector支持

c.push_front(t) 在c头部加入元素t ——list、deque支持,vector不支持。

c.insert(p, t)     在迭代器p指向的元素之前创建一个值为t的元素,返回指向新元素的迭代器。

c.insert(p, n, t) 在迭代器p指向的元素之前插入n个值为t的元素,返回指向新添加第一个元素的迭代器。

c.insert(p, b, e)将迭代器b和e指定的范围内的元素插入到迭代器p指向的元素之前。

使用deque中的push_front:

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

int main()
{
	string s;
	deque<string> vecStr;

	while(cin >> s)
	{
		vecStr.push_front(s);
	}
	for(deque<string>::const_iterator i = vecStr.begin(); i!=vecStr.end(); i++)
	{
		cout << *i << endl;
	}

	return 0;
}

使用insert1:

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

int main()
{
	string s;
	deque<string> vecStr;

	deque<string>::iterator idx = vecStr.begin();
	vecStr.insert(idx, "Hello");//insert ibefore first element
	//same as vecStr.push_front("Hello");

	while(cin >> s)
	{
		vecStr.push_back(s);
	}

	for(deque<string>::const_iterator i = vecStr.begin(); i!=vecStr.end(); i++)
	{
		cout << *i << endl;
	}

	return 0;
}

使用insert2:

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

int main()
{
	string s;
	deque<string> vecStr;

	deque<string>::iterator idx = vecStr.begin();
	vecStr.insert(idx, "Hello");//insert ibefore first element
	//same as vecStr.push_front("Hello");

	while(cin >> s)
	{
		vecStr.push_back(s);
	}

	string sArr[] = {"I", "Love", "You"};
	deque<string> vec(sArr, sArr+sizeof(sArr)/sizeof(sArr[0]));
	//deque<string> vec(3,"You");
	vecStr.insert(idx, vec.begin(), vec.end());

	for(idx = vecStr.begin(); idx!=vecStr.end(); idx++)
	{
		cout << *idx << endl;
	}

	return 0;
}

删除元素:

c.pop_back() 删除c中尾元素

c.pop_front() 删除c中首元素——同样,vector不支持

c.erase(p)     删除迭代器p指向的元素,返回一个执行被删元素之后元素的迭代器

c.erase(b, e) 删除迭代器b、e范围内元素

c.clear()        删除c中所有元素

使用erase 1:

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

int main()
{
	int num = 1;
//	vector<int> vec = {10, 1}; Error
	vector<int> vec(10, 2);
	vector<int>::iterator i;

	//vec.pop_back();
	vec.insert(vec.begin(), 3, 3);
	vec.erase(vec.begin());

	for(i = vec.begin(); i!=vec.end(); ++i)
	{
		cout << num++ << ": " << *i << endl;
	}

	return 0;
}

使用erase 2:

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

int main()
{
	int num = 1;
//	vector<int> vec = {10, 1}; Error
	vector<int> vec(10, 2);
	vector<int>::iterator i;

	//vec.pop_back();
	vec.insert(vec.begin(), 3, 3);
	vec.erase(vec.begin(), vec.begin()+2);

	for(i = vec.begin(); i!=vec.end(); ++i)
	{
		cout << num++ << ": " << *i << endl;
	}

	return 0;
}

按理说上面的erase应该把3个3都删除了,可运行结果是还保留了一个3,原因应该是像迭代器的左闭右开区间:

erase(vec.begin(), vec.begin()+2);    //不删除vec.begin()+2指向的元素

改变容器大小:

list<int> ilist(10, 20); //10个int 每个都是20
ilist.resize(15); //将5个值为0的元素添加到ilist末尾
ilist.resize(25, -1); //将10个值为-1的元素添加到ilist末尾
ilist.resize(5); //从ilist末尾删除20个元素

3.迭代器

标准容器类型上所有迭代器都允许我们访问容器中的元素,而所有迭代器都是通过解引用运算符来实现这个操作的。

迭代器范围:一个左闭右开区间[begin, end);

iterator、const_iterator、reverse_iterator、const_reverse_iterator;

获取容器迭代器:

vector<int> vec(10);//vec含10个元素,每个元素都是0
vector<int>::iterator i = vec.begin();//获取指向第一个元素的迭代器。
*i = 10;//解引用可以作为左值改变容器中的值

注意:向容器中添加元素和从容器中删除元素的操作可能会使指向容器元素的迭代器、指针、引用失效。因此必须保证每次改变容器的操作之后都能正确的重新定位迭代器。

4.vector是如何增长的?

标准库实现采用了可以减少容器重新分配次数的策略。当不得不获取新空间时,vector和string的实现通常会分配比新的空间需求更大内存空间。预留这些空间作为备用,可以用来保存更多的新元素。

capacity与size:

size是已经保存的元素的数目。capacity是在不分配新的内存空间下最多可以保存多少元素。capacity应该至少和size一样大。

例子:

vector<int> vec;
cout << "vec.size: " << vec.size() << end;
cout << "vec.capacity: " << vec.capacity() << end;

for(int i  = 0; i<24; i++)
      vec.pusk_back(i);

cout << "vec.size: " << vec.size() << end;
cout << "vec.capacity: " << vec.capacity() << end;

运行结果如下:

vec.size: 0

vec.capacity: 0

vec.size: 24

vec.capacity: 32

可以想象当前vec的状态:

[0] [1] [2] ...... [23] [.....保留空间.....]

c.reserve(n); //分配至少能容纳n个元素的内存空间
vec.reserve(50);

cout << "vec.size: " << vec.size() << endl;
cout << "vec.capacity: " << vec.capacity() << endl;

结果:

vec.size: 0

vec.capacity: 0

vec.size: 24

vec.capacity: 50

课后习题:

#include <iostream>
#include <vector>

using namespace std;

int main()
{
	vector<string> vec;
	string s = "hello";

	cout << "vec.size: " << vec.size() << endl;
	cout << "vec.capacity: " << vec.capacity() << endl;
	vec.reserve(1024);

	for(int i = 0; i<24; i++)
	{
		vec.push_back(s);
	}
	vec.resize(vec.size() + vec.size()/2);//当前size为24 24+12=36 因此当前size变为36

	cout << "vec.size: " << vec.size() << endl;
	cout << "vec.capacity: " << vec.capacity() << endl;
	return 0;
}

C++ Primer笔记5_STL之顺序容器

时间: 2024-10-29 03:41:20

C++ Primer笔记5_STL之顺序容器的相关文章

C++ primer笔记——第九章 顺序容器

顺序容器的元素按照其位置存储和访问.除了顺序容器之外,标准库还提供了几种关联容器,其元素按照键(key)排序.每组容器都提供一组不同的时间和功能的折中方案.顺序容器根据位置来存储和访问元素,元素的排列次序与元素值无关,而是由元素添加到容器的顺序决定.标准库定义了三种顺序容器:vector.list.dequeue.他们的差别在于元素访问的方式以及添加和删除元素相关操作的运行代价.标准库还提供了三种适配器.适配器是根据原始的容器类型所提供的操作,通过定义新的操作接口来适应基础的容器类型.顺序容器适

0716-----C++Primer听课笔记----------STL之顺序容器、迭代器

1. 顺序容器的初始化操作 1.1 顺序容器(vector,list,deque)的五种初始化方法,以 vector 为例. #include <iostream> #include <string> #include <vector> using namespace std; int main(int argc, const char *argv[]) { //1.定义空数组 然后后面追加 vector<string> vec1; vec1.push_ba

C++ Primer笔记7_STL之关联容器

关联容器 与顺序容器不同,关联容器的元素是按关键字来访问和保存的.而顺序容器中的元素是按他们在容器中的位置来顺序保存的. 关联容器最常见的是map.set.multimap.multiset map的元素以键-值[key-value]对的形式组织:键用作元素在map中的索引,而值则表示所存储和读取的数据. set仅包含一个键,并有效的支持关于某个键是否存在的查询. pair类型 首先介绍下pair,pair定义在utility头文件中,一个pair保存两个数据成员,类似容器,pair是一个用来生

【足迹C++primer】26、顺序容器操作

顺序容器操作 向顺序容器添加元素 forward_list //有自己专有版本的insert和emplace: forward_list //不支持push_back和emplace_back vector, string //不支持push_front和emplace_front c.push_back(t), c.emplace_back(args) //在c的尾部创建一个值为t的或者由args创建的元素,返回void c.push_front(t), c.emplace_back(args

Accelerated C++学习笔记7—&lt;使用顺序容器并分析字符串&gt;

第6章  使用库算法 本章中主要教我们如何使用几个库算法来解决与处理字符串和学生成绩相关的问题. 1.分析字符串 使用一个循环来连接两幅字符图案 for(vector<string>::const_iterator it = bottom.begin(); it != bottom.end(); ++it) ret.push_back(*it);</span> 等价于 ret.insert(ret.end(), bottom.begin(), bottom.end());</

C++ Primer 第四版读书笔记(八)之顺序容器(续)

3.6 访问元素 如果容器非空,那么容器类型的front和back成员将返回容器内第一个或最后一个元素的引用. 访问顺序容器内元素的操作 c.back() 返回容器c的最后一个元素的引用.如果c为空,则该操作未定义 c.front() 返回容器c的第一个元素的引用.如果c为空,则该操作未定义 c[n] 返回下标为n的元素的引用 如果n<0或n>c.size(),则该操作未定义 只适用于vector和deque容器 c.at[n] 返回下标为n的元素的引用.如果下标越界,则该操作未定义 只适用于

C++ Primer 第四版读书笔记(八)之顺序容器

容器容纳特定类型对象的集合. 标准库vector类型,是一个顺序容器.它将单一类型元素聚集起来称为容器,然后根据位置来存储和访问这些元素,这就是顺序容器.顺序容器的元素排列次序与元素值无关,而是由元素添加到容器里的次序决定. 标准库定义了三种顺序容器类型:vector.list和deque.它们的差别在于访问元素的方式,以及添加或删除元素相关操作的运行代价.标准库还提供了三种容器适配器.实际上,适配器是根据原始的容器类型所提供的操作,通过定义新的操作接口,来适应基础的容器类型. 顺序容器类型 顺

C++primer笔记:IO库、顺序容器、关联容器、面向对象、泛型算法、模板和泛型编程

第八章:IO库不直接来处理输入输出,而是通过在标准库中的一些类型来处理io istream ostream cin cout cerr getline函数 iostream:定义了用于基本读写流的基本类型 fstream: 定义了基本的读写命名文件的类型 sstream:定义了读写内存的string对象的类型 IO对象无拷贝或者赋值 条件状态:IO定义了一些函数和标志,可以帮助我们访问和操作流得条件状态 strm::iostate 条件状态的完整功能 strm::badbit 流已崩溃 strm

C++primer(第五版)第九章 顺序容器(容器的运用及其部分习题解答,C++11特性总结,重点章节内容较多)

顺序容器:为程序员提供了控制元素存储和访问顺序的能力.(无序容器)           1.顺序容器的概述           A.顺序容器的类型           vector:可变大小数组.支持快速随机访问.在尾部之外的位置插入或删除元素可能很慢.          deque:双端队列.支持快速随机访问.在头尾位置插入/删除速度很快.           list:双向链表.只支持双向顺序访问.在list中任何位置进行插入/删除操作速度都很快.          forword_list