c/c++1-STL
1,STL序列式容器
- array、vector、deque、list 和 forward_list 容器,其共同的特点是不会对存储的元素进行排序,元素排列的顺序取决于存储它们的顺序。
序列式容器类别 | 特点 |
---|---|
array<T,N>(数组容器) | 表示可以存储 N 个 T 类型的元素,是 C++ 本身提供的一种容器。此类容器一旦建立,其长度就是固定不变的,这意味着不能增加或删除元素,只能改变某个元素的值。简单地理解,它就是在 C++ 普通数组的基础上,添加了一些成员函数和全局函数。在使用上,它比普通数组更安全,且效率并没有因此变差。 |
vector |
用来存放 T 类型的元素,是一个长度可变的序列容器,即在存储空间不足时,会自动申请更多的内存。使用此容器,在尾部增加或删除元素的效率最高(时间复杂度为 O(1) 常数阶),在其它位置插入或删除元素效率较差(时间复杂度为 O(n) 线性阶,其中 n 为容器中元素的个数) |
deque |
和 vector 非常相似,区别在于使用该容器不仅尾部插入和删除元素高效,在头部插入或删除元素也同样高效,时间复杂度都是 O(1) 常数阶,但是在容器中某一位置处插入或删除元素,时间复杂度为 O(n) 线性阶 |
list |
是一个长度可变的、由 T 类型元素组成的序列,它以双向链表的形式组织元素,在这个序列的任何地方都可以高效地增加或删除元素(时间复杂度都为常数阶 O(1)),但访问容器中任意元素的速度要比前三种容器慢,这是因为 list |
forward_list |
和 list 容器非常类似,只不过它以单链表的形式组织元素,它内部的元素只能从第一个元素开始访问,是一类比链表容器快、更节省内存的容器 |
- array
std::array<double, 10> values; std::array<double, 10> values {}; //将所有的元素初始化为 0 或者和默认元素类型等效的值 std::array<double, 10> values {0.5,1.0,1.5,,2.0};
array<char, 50> values {1,2,3}; values.data() 与 &values[0] 等价 cout<<values.data()<<endl; cout<<&values[0];
- vector
//创建 vector<double> values; //这是一个空的 vector 容器,因为容器中没有元素,所以没有为其分配空间。当添加第一个元素(比如使用 push_back() 函数)时,vector 会自动分配内存。 values.reserve(20); //在创建好空容器的基础上,可以通过调用 reserve() 成员函数来增加容器的容量。 vector<int> primes {2, 3, 5, 7, 11, 13, 17, 19}; vector<double> values(20); vector<double> values(20, 1.0); //第二个参数指定了所有元素的初始值,因此这 20 个元素的值都是 1.0;圆括号 () 中的 2 个参数,既可以是常量,也可以用变量来表示 //增 values.push_back(elem) //push_back() 向容器尾部添加元素时,首先会创建这个元素,然后再将这个元素拷贝或者移动到容器中(如果是拷贝的话,事后会自行销毁先前创建的这个元素) values.emplace_back(elem) //emplace_back() 在实现时,是直接在容器尾部创建这个元素,省去了拷贝或移动元素的过程。 values.insert(pos,elem) //在指定的位置之前插入一个新元素elem,并返回表示新插入元素位置的迭代器。 values.insert(pos,n,elem) //在指定的位置之前插入 n 个元素 elem,并返回表示第一个新插入元素位置的迭代器。 values.insert(pos,first,last) //在指定的位置之前,插入其他容器(不仅限于vector)中位于 [first,last) 区域的所有元素,并返回表示第一个新插入元素位置的迭代器,values.insert(values.end(), array.begin(), array.end()) values.insert(pos, initlist) //在指定的位置之前,插入初始化列表(用大括号{}括起来的多个元素,中间有逗号隔开)中所有的元素,并返回表示第一个新插入元素位置的迭代器。 values.emplace(pos, elem) //删 values.pop_back() values.erase(pos) swap(values[pos1], values[pos2]) pop_back() //先调用 swap() 函数交换要删除的目标元素和容器最后一个元素的位置,然后使用 pop_back() 删除该目标元素。 values.erase(beg, end) //删除 vector 容器中位于迭代器 [beg,end)指定区域内的所有元素,并返回指向被删除区域下一个位置元素的迭代器。 remove(beg, end, elem) //删除容器中所有和指定元素值相等的元素,并返回指向最后一个元素下一个位置的迭代器。 values.clear() //删除 vector 容器中所有的元素,使其变成空的 vector 容器。 //改 //查 values[n] //注意判断边界 values.at(n) values.front() //首元素的引用 values.back() //尾元素的引用 values.data() //指向首个元素的指针(&values[0]) values.capacity() //在不分配更多内存的情况下,容器可以保存的最多元素个数 values.size() //容器中实际存储的元素个数 vector<int>::size_type/auto cap = values.capacity(); //定义一个变量保存容器的容量和大小 vector<int>::size_type/auto size = values.size(); //定义一个变量保存容器的容量和大小 values.begin() //指向容器中第一个元素的正向迭代器 values.end() //指向容器最后一个元素之后一个位置的正向迭代器
- deque(双端队列容器,在两端添加或者删除元素,时间复杂度都是常数阶O(1))
'''创建''' deque<int> d; deque<int> d(10); deque<int> d(10, 5); deque<int> d2(d1); //拷贝普通数组,创建deque容器 int a[] = { 1,2,3,4,5 }; deque<int>d(a, a + 5); //适用于所有类型的容器 array<int, 5>arr{ 11,12,13,14,15 }; deque<int>d(arr.begin()+2, arr.end());//拷贝arr容器中的{13,14,15} '''增''' d.push_back(elem); d.push_front(elem); d.emplace_back(elem); d.emplace_front(elem); d.emplace(pos, elem); d.insert(pos, elem); d.insert(pos, num, elem); d.insert(pos, other_pos1, other_pos2); d.insert(pos, {...}); '''删''' d.pop_back(elem); d.pop_front(elem); d.erase(pos); d.erase(pos1,pos2); '''查''' d[pos]; d.at(pos); d.front(); d.back() '''改''' d[pos] = elem; d.at(pos) = elem; d.front() = elem; d.back() = elem;
- list(双向链表容器,该容器的元素可以分散存储在内存空间中,而不是必须存储在一整块内存空间中。它可以在序列已知的任何位置快速插入或删除元素(时间复杂度为O(1))。并且在 list 容器中移动元素,也比其它容器的效率高。使用 list 容器的缺点是,它不能像 array 和 vector 那样,通过位置直接访问元素,即它不支持容器对象名[6]这种语法格式。正确的做法是从容器中第一个元素或最后一个元素开始遍历容器,直到找到该位置。)
'''创建''' list<int> values; list<int> values(10); list<int> values(10, 5); list<int> value2(value1); //通过拷贝其他类型容器(或者普通数组)中指定区域内的元素,创建新的 list 容器。 int a[] = { 1,2,3,4,5 }; list<int> values(a, a+5);
行动是治愈恐惧的良药,而犹豫拖延将不断滋养恐惧。