顺序容器
概念:
顺序容器提供了快速顺序访问元素的能力,这些容器在某些方面都有不同的性能折中
①向容器添加或从容器删除元素的代价
②非顺序访问容器中元素的代价
- vector:可变大小数组。支持快速随机访问。在尾部之外的位置插入或删除元素可能很慢
- deque:双端队列。支持快速随机访问。在头尾位置插入/删除速度很快
- list:双向链表。只支持双向顺序访问。在list中任何位置进行插入/删除操作很快
- forward_list:单向链表。只支持单向顺序访问,在链表任何位置进行插入/删除操作速度都很快(其设计目的达到与手写单向链表的性能)
- array:固定大小数组。支持快速随机访问。不能删除或添加元素
- string:与vector相似的容器,但专门用于保存字符。随机访问快,在尾部插入/删除速度快
顺序容器操作:
- 向顺序容器添加元素
- push_back() string,vector,list和deque支持
- push_front() forward_list,list和deque支持
- Insert() string,vector,list和deque支持(可插入到容器的任意位置,其实现原理为元素拷贝,即放入到容器中的对象指为一个拷贝,而不是对象本身。容器中的元素与提供值的对象之间没有任何关联,随后对容器中的元素的任何改变都不会影响原始对象)
- 在顺序容器删除元素
- pop_back() string,vector,list和deque支持
- pop_front() forward_list,list和deque支持
- erase() string,vector,list和deque支持
- 访问元素
- back() 除了 forward_list其他都有
- front() 顺序容器都有该操作
- at() 只适用于string,vector,deque和array(如果下标越界,则抛出out-of-range异常,下标运算符号[]并不检查是否在合法范围内)
在容器中访问元素的成员函数返回的都是引用,如果容器是一个const对象,则返回值为const引用
容器适配器(不支持迭代器)
概念:
适配器是一种机制,使某种事物的行为看上去像另一种事物一样。一个容器适配器接受一种已有的容器类型,使其看起来像一种不同的类型
- stack 构造于顺序容器(除array或forward_list外)
- queue 构造于list或deque
关联容器
概念:
关联容器中的元素是根据关键字存储的,其不支持顺序容器的位置相关操作,其也不支持构造函数或插入操作
- Map 关联数组;保存关键字-值对
- Set 关键字即值,即只保存关键的容器
- Multi 即可重复出现
- Unordered 用哈希函数组织的
- Pair 一个pair用来保存两个数据成员,两个成员分别命名为first,second,初始化如pair<string,string> author{“James”,“Joyce”}
关联容器操作:
1. 迭代器:其迭代操作和顺序容器类似,但set中的元素是const的,map中pair其第一个成员是const key,第二个成员是value
2. 添加元素:insert(),其返回值为pair类型,pair的first成员是一个迭代器指向具有给定关键字的元素,second成员是bool类型,表示是否插入成功。
map.insert(pair<int, string>(key, "value")); 或 map.insert(make_pair(key,"value"));
3. 删除元素:erase(),其有两种用法 ①删除每个关键字为k的元素,返回删除元素的数量 ②删除迭代器指向的元素,不能为end(),返回p之后的迭代器
4. 访问元素:map[k];返回关键字为k的元素值,若其不在map当中,则添加进去并初始化。
迭代器
概念:
- 标准容器类型上的所有迭代器都允许我们访问容器中的元素,而所有迭代器都是通过解引用运算来实现这个操作。
- begin和end操作生成容器中第一个元素和尾元素之后位置的迭代器,这两个迭代器最常见的用途就是形成一个包含容器中所有元素的迭代器
泛型算法迭代器种类:
- 输入迭代器:只读,不写,单遍扫描,只能递增
- 输出迭代器:只写,不读,单遍扫描,只能递增
- 单向迭代器:可读写,多遍扫描,只能递增
- 双向迭代器:可读写,多遍扫描,可递增递减
- 随机访问迭代器:可读写,多遍扫描,支持全部迭代器操作
容器操作后迭代器相关情况:
- 向容器添加元素后
- 如果容器是vector或string,且存储空间会被重新分配,则指向容器的迭代器、指针和引用都会失效。如果存储空间未重新分配,指向插入位置之前的元素迭代器,指针和引用仍有效,但之后位置都将会失效
- 对于deque,插入到除首尾位置之外的任何位置都会导致迭代器,指针和引用失效。如果在首尾位置添加元素,迭代器将会失效,但指向存在的元素的引用和指针不会失效
- 对于list和forward_list,指向容器的迭代器,指针和引用有效(删除亦同)
- 向容器删除元素后
- 对于vector和string,指向被删元素之前的迭代器,引用和指针仍有效(尾后迭代器总是会失效),之后都是会失效
- 对于deque,删除除首尾位置之外的任何位置都会导致迭代器,指针和引用失效。如果删除deque的尾元素,则尾后迭代器失效,其他不受影响;删除deque的首元素,则这些不受影响
String字符串
顺序容器操作:
1.构造函数
string s1(4, 'K'); // s1 = "KKKK"
string s2("12345", 1, 3); //s2 = "234",即 "12345" 的从下标 1 开始,长度为 3 的子串
2.字符串长度
string s1("123");
s1.length();//3
s1.size();//3
s1.clear(); //移除全部字符
s1.capacity(); //返回之前字符的容量
s1.empty(); //判断字符串是否为空
3.字符串连接
string s1("123"), s2("abc");
s1.append(s2); // s1 = "123abc"
s1.append(s2, 1, 2); // s1 = "123abcbc"
s1.append(3, 'K'); // s1 = "123abcbcKKK"
s1.append("ABCDE", 2, 3); // s1 = "123abcbcKKKCDE",添加 "ABCDE" 的子串(2, 3)
4.字符串比较
string s1("hello"), s2("hello, world");
int n = s1.compare(s2); //s2大则为1,s2小则为-1
n = s1.compare(1, 2, s2, 0, 3); //比较s1的子串 (1,2) 和s2的子串 (0,3)
n = s1.compare(0, 2, s2); // 比较s1的子串 (0,2) 和 s2
n = s1.compare("Hello");
n = s1.compare(1, 2, "Hello"); //比较 s1 的子串(1,2)和"Hello”
n = s1.compare(1, 2, "Hello", 1, 2); //比较 s1 的子串(1,2)和 "Hello" 的子串(1,2)
5.字符串字串
string s1 = "this is ok";
string s2 = s1.substr(2, 4); // s2 = "is i" 包含开始字符在内的总共4个字符
s2 = s1.substr(2); // s2 = "is is ok" 包含开始字符到字符尾
6.交换字符串
string s1("West"), s2("East");
s1.swap(s2); // s1 = "East",s2 = "West"
7.查找字符串
find:从前往后查找子串或字符出现的位置。s1.find(' ',n); //从n开始查找' '
rfind:从后往前查找子串或字符出现的位置。
find_first_of:从前往后查找第一次出现字串的位置
find_last_of:从后往前查找第一次出现字串的位置。
8.替换子串
string s1("Real Steel");
s1.replace(1, 3, "123456", 2, 4); //用 "123456" 的子串(2,4) 替换 s1 的子串(1,3)
cout << s1 << endl; //输出 R3456 Steel
string s2("Harry Potter");
s2.replace(2, 3, 5, '0'); //用 5 个 '0' 替换子串(2,3)
cout << s2 << endl; //输出 HaOOOOO Potter
int n = s2.find("OOOOO"); //查找子串 "00000" 的位置,n=2
s2.replace(n, 5, "XXX"); //将子串(n,5)替换为"XXX"
cout << s2 < < endl; //输出 HaXXX Potter
9.删除子串
string s1("Real Steel");
s1.erase(1, 3); //删除子串(1, 3),此后 s1 = "R Steel"
s1.erase(5); //删除下标5及其后面的所有字符,此后 s1 = "R Ste"
10.插入子串
string s1("Limitless"), s2("00");
s1.insert(2, "123"); //在下标 2 处插入字符串"123",s1 = "Li123mitless"
s1.insert(3, s2); //在下标 3 处插入 s2 , s1 = "Li10023mitless"
s1.insert(3, 5, 'X'); //在下标 3 处插入 5 个 'X',s1 = "Li1XXXXX0023mitless"
11.字符串反转
s==string(s.rbegin(),s.rend()) ; //判断回文
reverse(s.begin(),s.end()); //字符串反转