容器
vector
给定类型元素的序列,元素在内存中是连续存储的。
1. 初始化
要初始化 std::vector 类模板,可以使用以下方法中的任何一种(但不限于这些):
1) 从初始化列表进行初始化:
std::vector<int> v1 { 1, 2, 3, 4, 5 };
2) 从数组初始化:
int arr[] = { 1, 2, 3, 4, 5 };
std::vector<int> v21(arr, arr + 5); // v21 = { 1, 2, 3, 4, 5 }
std::vector<int> v222(arr+1, arr+4); // v222 = { 2, 3, 4 }
assign() 方法用 begin 和 end 迭代器定义的另一个序列进行赋值,这将替换容器的内容:
v31.assign(arr, arr + 5); // v31 = { 1, 2, 3, 4, 5 }
3) 从另一个容器初始化:
std::list<int> l { 1, 2, 3, 4, 5 };
std::vector<int> v3(l.begin(), l.end()); // { 1, 2, 3, 4, 5 }
4) 从计数和值初始化:
std::vector<int> v4(5, 1); // {1, 1, 1, 1, 1 }
vector<int> v1={1,2,3,4,5};
vector<string> v2;
vercor<Shape*> v3(23); //size为23,元素初始值为nullptr
vector<double> v4(32, 9.9); //size为32,初始值为32个9.9
2. 库函数
末尾插入: v1.push_back(6);
末尾移除: v1.pop_back();
末尾创建一个元素再插入: emplace_back
struct foo
{
int a;
std::string c;
foo(int a, std::string const &c):a(a), c(c) {}
};
std::vector<foo> v3;
v3.emplace_back(1, "one"); //v3 = { foo{1, "one"}}
任意位置创建一个元素来插入: emplace
v3.emplace(v3.begin(), 2, "two"); //v3 = { foo{2, "two"}, foo{1, "one"}}
任意位置插入:
int arr[] = {1,2,3,4,5};
std::vector<int> v21;
v21.insert(v21.begin(), arr, arr+3); //v21 = {1,2,3};
删除: v1.erase(v1.begin()+2); v1.erase(v1.begin() + 2, v1.begin() + 4); //第3 和 4元素被删除,
清空: v1.clear();
访问元素: v1[2]; or v1.at(2)
迭代访问:
可以使用迭代器遍历 vector 中的元素:
for (auto it = v1.begin(); it != v1.end(); ++it) {
std::cout << *it << " ";
}
或者使用范围循环:
for (int element : v1) {
std::cout << element << " ";
}
list 双向链表
不支持下标操作
https://c.biancheng.net/view/6892.html
vector 无论是遍历(find()和count())性能还是排序和搜索(sort()和binary_search())性能都优于list。
map 搜索树(红黑树) 有序
map支持下标操作。
搜索map的时间代价是O(logN),包含100万个元素的map,只需要20次比较和间接寻址就可以找到元素。
unordered_map 哈希表 无序
unordered_map<string, int> phone_book {
{"David", 123456},
{"Karle", 234567},
{"Bertr", 345678}
}
int get_number(const string& s)
{
return phone_book[s];
}
迭代器
begin() end() find() 返回的是指向元素的迭代器。
例1
bool has_c(const string& s, char c)
{
return find(s.begin(), s.end(), c) != s.end();
}
例2
vector<string::iterator> find_all(string& s, char c) // vector,每个元素都是一个指向string的迭代器
{
vector<string::iterator> res;
for(auto p = s.begin(); p != s.end(); ++p)
{
if (*p == c)
{
res.push_back(p);
}
}
return res;
}
例3
template<typename T>
using Iterator<T> = typename T::iterator;
template<typename C, typename V>
vector<Iterator<C>> find_all(C &c, V v)
{
vector<Iterator<C>> res;
for (auto p = c.begin(); p != c.end(); ++p)
{
if (*p == v)
res.push_back(p);
}
return res;
}
迭代器本质上是什么?
每个迭代器都是与某个特定容器类型相关联的。有多少种容易就是有多少种迭代器。
vector的迭代器可能就是一个普通指针,也可以是一个指向一个vector的指针加上一个索引。
对任何迭代器使用++运算符都会得到一个指向下一个元素的迭代器,而*运算符则得到迭代器所指的元素。