C++ STL容器总结(一)——顺序性容器

C++ STL总结(一)

  • 顺序性容器
    • 概述
    • 通用容器操作
      • 构造函数
      • 赋值与swap
      • 大小
      • 添加/删除元素(不适用于array)
      • 获取迭代器
      • 反向容器的额外成员(不支持forward_list)
    • vector && deque && list
      • vector
        • 特性
        • 常用函数
        • 嵌套vector初始化
      • deque
      • list
      • string

通用容器的分类
STL 对定义的通用容器分三类:顺序性容器,关联式容器和容器适配器。

顺序性容器:是一种各元素之间有顺序关系的线性表,是一种线性结构的可序群集。顺序性容器中的每个元素均有固定的位置,除非用删除或插入的操作改变这个位置。这个位置和 元素本身无关,而和操作的时间和地点有关,顺序性容器不会根据元素的特点排序而是直接保存了元素操作时的逻辑顺序。比如我们一次性对一个顺序性容器追加三 个元素,这三个元素在容器中的相对位置和追加时的逻辑次序是一致的。

关联式容器:和顺序性容器不一样,关联式容器是非线性的树结构,更准确的说是二叉树结构。各元素之间没有严格的物理上的顺序关系,也就是说元素在容器中并没有保存元素置 入容器时的逻辑顺序。但是关联式容器提供了另一种根据元素特点排序的功能,这样迭代器就能根据元素的特点“顺序地”获取元素。
关联式容器另一个显著的特点是它是以键值的方式来保存数据,就是说它能把关键字和值关联起来保存,而顺序性容器只能保存一种(可以认为它只保存关键字,也可以认为它只保存值)。这在下面具体的容器类中可以说明这一点。

容器适配器:是一个比较抽象的概念, C++的 解释是:适配器是使一事物的行为类似于另一事物的行为的一种机制。容器适配器是让一种已存在的容器类型采用另一种不同的抽象类型的工作方式来实现的一种机 制。其实仅是发生了接口转换。那么你可以把它理解为容器的容器,它实质还是一个容器,只是他不依赖于具体的标准容器类型,可以理解是容器的模版。或者把它 理解为容器的接口,而适配器具体采用哪种容器类型去实现,在定义适配器的时候可以由你决定。

标准容器类 特点
顺序容器类
vector 可变大小数组。支持快速随机访问。在尾部之外的位置插入或删除元素可能很慢
deque 双端对列。支持快速随机访问。在头尾位置插入/删除速度很快
list 双向链表。只支持双向顺序访问。在list中任何位置进行插入/删除操作速度都很快
forward_list 单向链表。只支持单向顺序访问。在链表任何位置进行插入/删除操作速度都很快
array 固定大小数组。支持快速随机访问。不能添加或删除元素
string 与vector相似的容器,但专门用于保存字符。随机访问快。在尾部插入/删除速度快
关联式容器
set 快速查找,不允许重复值
multiset 快速查找,允许重复值
map 一对多映射,基于关键字快速查找,不允许重复值
multimap 一对多映射,基于关键字快速查找,允许重复值
容器适配器
stack 后进先出
queue 先进先出
priority_queue 最高优先级元素总是第一个出列

顺序性容器

概述

除了固定大小的array外,其他容器都提供高效、灵活的内存管理。容器保存元素的策略对容器操作的效率有着固有的,有时是重大的影响。

string和vector将元素保存在连续的内存空间中。由于元素是连续存储的,由元素的下标来计算其他地址是非常快速的。但是,在这两种容器的中间位置添加或者删除元素就会非常耗时:在一次插入或删除操作后,需要移动插入/删除位置之后的所有元素,来保持连续存储。而且,添加一个元素有时可能还需要分配额外的存储空间。在这种情况下,每个元素都必须移动到新的存储空间。

list和forward_list两个容器的设计目的是令容器任何位置的添加和删除操作都很快速。这两个容器都不支持随机访问。另外,与vector、deque、array相比,这两个容器的额外内存开销更大。

deque是一个更为复杂的数据结构。与string、vector类似,deque支持快速的随机访问。与string和vector一样,在deque的中间位置添加或删除元素的代价(可能)很高。但是,在deque的两端添加或删除元素都很快。

forward_list和array是新C++标准增加的类型。与内置数组相比,array是一种更安全、更容易使用的数据类型。与内置数组类似,array对象的大小是固定的。forward_list的设计目标是达到与最好的手写的单向链表数据结构相当的性能。因此,forward_list没有size操作,因为保存或计算其大小就会比手写链表多出额外的开销。

通常,使用vector是最好的选择,除非你有很好的理由选择其他容器

通用容器操作

构造函数

C c;  //默认构造函数,构造空容器
C c1(c2);  //构造c2的拷贝c1
C c(b, e);  //构造c,将迭代器b和e指定的范围内的元素拷贝到c(array不支持)
C c(a, b, c...);  //列表初始化c

赋值与swap

c1 = c2
c1 = {a, b, c...}
a.swap(b)  //交换a和b的元素
swap(a, b)   //与a.swap(b)等价

大小

c.size()  //c中元素的数目(不支持forward_list)
c.max_size()  //c可保存的最大元素数目
c.empty()

添加/删除元素(不适用于array)

c.insert(args)
c.emplace(inits)
c.erase(args)
c.clear()

获取迭代器

c.begin(), c.end()  //返回指向c的首元素和尾元素之后的位置的迭代器
c.cbegin(), c.cend()  //返回const_iterator

反向容器的额外成员(不支持forward_list)

reverse_iterator  //按逆序寻址元素的迭代器
const_reverse_iterator  //不能修改元素的逆序迭代器
c.rbegin(), c.rend()  //返回指向c的尾元素和首元素之前位置的迭代器
c.crbegin(), c.crend()  //返回const_reverse_iterator

vector && deque && list

vector 是一段连续的内存块,而deque 是多个连续的内存块, list 是所有数据元素分开保存,可以是任何两个元素没有连续。

vector 的查询性能最好,并且在末端增加数据也很好,除非它重新申请内存段;适合高效地随机存储。

list 是一个链表,任何一个元素都可以是不连续的,但它都有两个指向上一元素和下一元素的指针。所以它对插入、删除元素性能是最好的,而查询性能非常差;适合 大量地插入和删除操作而不关心随机存取的需求。

deque 是介于两者之间,它兼顾了数组和链表的优点,它是分块的链表和多个数组的联合。所以它有被list 好的查询性能,有被vector 好的插入、删除性能。 如果你需要随即存取又关心两端数据的插入和删除,那么deque 是最佳之选。

C++ STL容器总结(一)——顺序性容器_第1张图片

vector

特性

1. 顺序序列
2. 动态数组
3. 能够感知内存分配器的(Allocator-aware)

常用函数

1.构造函数

vector()  //创建一个空vector
vector(int nSize)  //创建一个vector,元素个数为nSize
vector(int nSize, const t& t)  //创建一个vector, 元素个数为nSize,且值均为t
vector(const vector&)  //复制构造函数
vector(begin, end)  //复制[begin, end)区间内的另一个数组的元素到vector中

2.增加函数

void push_back(const T& x)  //向量尾部增加一个元素x
iterator insert(iterator it, const T& x)  //向量中迭代器指向元素前增加一个元素x
iterator insert(iterator it, int n, const T& x)  //向量迭代器指向元素前增加n个相同元素x
iterator insert(iterator it, const_iterator first, const_iterator last)  //向量中迭代器指向元素前插入另一个相同类型向量的[first, last)间的数据

3.删除函数

iterator erase(iterator it)  //删除向量中迭代器指向元素
iterator erase(iterator first, iterator last)  //删除向量中[first,last)中元素
void pop_back()  //删除向量中最后一个元素
void clear()  //清空向量中所有元素

4.遍历函数

reference at(int pos)  //返回pos位置元素的引用
reference front()  //返回首元素的引用
reference back()  //返回尾元素的引用
iterator begin()  //返回向量头指针,指向第一个元素
iterator end()  //返回向量尾指针,指向向量最后一个元素的下一个位置
reverse_iterator rbegin()  //反向迭代器,指向最后一个元素
reverse_iterator rend()  //反向迭代器,指向第一个元素之前的位置

5.大小函数

bool empty() const  //判断向量是否为空,若为空,则向量中无元素
int size() const  //返回向量中元素的个数
int capacity() const:  //返回当前向量张红所能容纳的最大元素值
int max_size() const  //返回最大可允许的vector元素数量值

6.定义二维数组

int main(){
	int N=5, M=6;
	vector> obj(N, vector(M));
	
	for(int i=0; i

嵌套vector初始化

//方法1
vector<vector<int>> vec(3, vector<int>(4, 0));  //3行4列值都为0的嵌套vector;

//方法2
vector<vector<int>> vec1 = vector<vector<int>>(3, vector<int>(4, 0));

deque

双端队列

特有操作

reference back() //返回容器的最后一个元素的引用。如果que为空,则该操作未定义。
reference front() //返回容器的第一个元素的引用。如果que为空,则该操作为空。

void pop_front() //删除头部数据。
void push_front(elem) //在头部插入一个数据。

list

双向链表

特有操作

reference back() //返回容器的最后一个元素的引用。如果容器为空,则该操作未定义。
reference front() //返回容器的第一个元素的引用。如果容器为空,则该操作为空。

void pop_front() //删除头部数据。
void push_front(elem) //在头部插入一个数据。 
void splice ( iterator position, list<T,Allocator>& x );  //实现list拼接的功能。将源list也就是x的内容部分或全部元素删除,拼插入到目的list中position前面。
void splice ( iterator position, list<T,Allocator>& x, iterator i );
void splice ( iterator position, list<T,Allocator>& x, iterator first, iterator last );

void remove (const value_type& val);  //从list中删除所有值为val的元素
void remove_if (Predicate pred)//pred可以是一个函数,也可以是一个class,但它需要有一个参数,且参数类型跟list中存储元素类型相同,满足条件就返回true

void unique();  //只能删除相邻的重复元素,然后保留第一个值,因此这个函数只对排好序的list有用
void unique (BinaryPredicate binary_pred);  //binary_pred可以是函数,也可以是class,但它需要有两个参数,且类型跟list中存储的值类型相同,满足某个条件就返回true

void merge(list &x);  //会将列表x中的元素按默认的顺序移入当前列表当中,此时列表x为空,当前列表仍为有序列表
void merge (list& x, Compare comp);  //comp可以为一个函数,要求有两个参数且参数类型跟list中存储的元素类型相同,当满足条件时返回true,merge就按照这个条件将两个列表合并

void sort();  //默认升序排列
void sort (Compare comp);  //comp可以是一个函数,要求有两个参数,类型跟list中元素类型相同,满足条件时返回true,sort()函数就按照comp中制定的规则对元素进行排序

void reverse();  //将list中元素的顺序逆转过来

string

size_t length() //Returns the length of the string, in terms of bytes.

char& front();
char& back();

string& operator+= (const string& str);
string& operator+= (const char* s);
string& operator+= (char c);
string& operator+= (initializer_list<char> il)

string& append (const string& str); //Extends the string by appending additional characters at the end of its current value:
string& append (const string& str, size_t subpos, size_t sublen);
string& append (const char* s);
string& append (const char* s, size_t n);
string& append (size_t n, char c);
template <class InputIterator>
	string& append (InputIterator first, InputIterator last);
string& append (initializer_list<char> il);

string& replace (size_t pos, size_t len, const string& str); //Replaces the portion of the string that begins at character pos and spans len characters

size_t find (const string& str, size_t pos = 0) const noexcept; //If no matches were found, the function returns string::npos.
size_t find_first_of (const string& str, size_t pos = 0) const noexcept;
size_t find_last_of (const string& str, size_t pos = npos) const noexcept;
size_t find_first_not_of (const string& str, size_t pos = 0) const noexcept;
size_t find_last_not_of (const string& str, size_t pos = npos) const noexcept;

string substr (size_t pos = 0, size_t len = npos) const; //Returns a newly constructed string object with its value initialized to a copy of a substring of this object.

int compare (const string& str) const noexcept;

istream& getline (istream&  is, string& str, char delim); //Extracts characters from is and stores them into str until the delimitation character delim is found

参考链接
https://www.cnblogs.com/xkfz007/articles/2534249.html

你可能感兴趣的:(c++/python)